If I have a file or directory that is a symbolic link and I commit it to a Git repository, what happens to it?
I would assume that it leaves it as a symbolic link until the file is deleted and then if you pull the file back from an old version it just creates a normal file.
What does it do when I delete the file it references? Does it just commit the dangling link?
From linux symlink manual (assuming you are in Linux):
A symbolic link is a special type of file whose contents are a string that is the pathname of another file, the file to which the link refers. (The contents of a symbolic link can be read using readlink(2).)
So a symbolic link is one more file, just as a
README.md or a
Makefile. Git just stores the contents of the link (i.e. the aforementioned path of the file system object that it links to) in a ‘blob’ just like it would for any other file. It then stores the name, mode and type (including the fact that it is a symlink) in the tree object that represents its containing directory.
When you checkout a tree containing the link, it restores the object as a symlink regardless of whether the target file system object exists or not.
If you delete the file that the symlink references it doesn’t affect the Git-controlled symlink in any way. You will have a dangling reference. It is up to the user to either remove or change the link to point to something valid if needed.
You can see what Git does with a symbolic link by adding it to the index. The index is like a pre-commit. When the index is committed, you can use
git checkout to bring everything that was in the index back into the working directory. So, what does Git do when you add a symbolic link to the index?
First, make a symbolic link:
$ ln -s /path/referenced/by/symlink symlink
Git doesn’t know about this file yet.
git ls-files lets you inspect your index (
$ git ls-files -s ./symlink [nothing]
Now, add the symbolic link to the index. When you add a file to the index, Git copies its contents in the object store.
$ git add ./symlink
So, what was added?
$ git ls-files -s ./symlink 120000 1596f9db1b9610f238b78dd168ae33faa2dec15c 0 symlink
The hash is a reference to the packed object that was created in the object store. You can examine this object if you look in
.git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15c in the root of your repository. This is the file that Git stores in the repository, that you can later check out. If you examine this file, you’ll see it is very small. It does not store the contents of the linked file. To confirm this, print the contents of the packed repository object with
$ git cat-file -p 1596f9db1b9610f238b78dd168ae33faa2dec15c /path/referenced/by/symlink
120000 is the mode listed in
ls-files output. It would be something like
100644 for a regular file.)
But what does Git do with this object when you check it out from the repository and into your filesystem? It depends on the
core.symlinks config. From
If false, symbolic links are checked out as small plain files that contain the link text.
So, with a symbolic link in the repository, upon checkout you either get a text file with a reference to a full filesystem path, or a proper symbolic link, depending on the value of the
Either way, the content of the path referenced by the symlink is not stored in the repository (unless the referenced path is also in the repository, of course).
“Editor’s” note: This post may contain outdated information. Please see comments and this question regarding changes in Git since 1.6.1.
It’s important to note what happens when there is a directory which is a soft link.
Any Git pull with an update removes the link and makes it a normal directory. This is what I learnt hard way. Some insights here and here.
ls -l lrwxrwxrwx 1 admin adm 29 Sep 30 15:28 src/somedir -> /mnt/somedir
It remains the same
git pull AND some updates found
drwxrwsr-x 2 admin adm 4096 Oct 2 05:54 src/somedir