symlinks - git symbolic-ref example




How does Git handle symbolic links? (2)

"Editor's" note: This post may contain outdated information. Please see comments and this question regarding changes in Git since 1.6.1.

Symlinked directories:

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.

Example

Before

 ls -l
 lrwxrwxrwx 1 admin adm   29 Sep 30 15:28 src/somedir -> /mnt/somedir

git add/commit/push

It remains the same

After git pull AND some updates found

 drwxrwsr-x 2 admin adm 4096 Oct  2 05:54 src/somedir

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?


TL;DR: The data referenced by the symlink is not stored in the repository.


You can find out what Git does with a file by seeing what it does when you add it to the index. The index is like a pre-commit. With the index 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?

To find out, 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 (-s prints stat-like output):

$ git ls-files -s ./symlink
$

Now, add the contents of the symbolic link to the Git object store by adding it to the index. When you add a file to the index, Git stores its contents in the Git 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 Git object store. You can examine this object if you look in .git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15c.

The 120000 is the file mode. It would be something like 100644 for a regular file and is the mode special for links. From man git-config:

core.symlinks

If false, symbolic links are checked out as small plain files that contain the link text. git-update-index(1) and git-add(1) will not change the recorded type to regular file.

Use git cat-file -p to pretty-print the contents:

$ git cat-file -p 1596f9db1
/Path/referenced/by/symlink

So, that's what Git does to a symbolic link: when you git checkout the symbolic link, you either get a text file with a reference to a full filesystem path, or a symlink, depending on configuration. The data referenced by the symlink is not stored in the repository.





symlink