Unfortunately after committing into Git, they've turned into plain text files. Note that even after committing and pushing into Git, the symlinks still work fine. However, after some branch switches and code merges, the symlinks become actual text files with the link target as the contents.
1 Answer. Git just stores the contents of the link in a 'blob'(binary large object) just like it would for a normal file. Then it stores a symlink (which comprises of name, mode, and type) in the tree object that represents its containing directory.
If you do not specify the -F, -d or -l options, ls(1) will follow symbolic links specified on the command line. If the -L flag is specified, ls(1) follows all symbolic links, regardless of their type, whether specified on the command line or encountered in the tree walk.
Git does not follow symbolic links when accessing a . gitignore file in the working tree. This keeps behavior consistent when the file is accessed from the index or a tree versus from the filesystem.
What I did to add to get the files within a symlink into Git (I didn't use a symlink but):
sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY
Do this command in the Git-managed directory. TARGETDIRECTORY
has to be created before the SOURCEDIRECTORY
is mounted into it.
It works fine on Linux, but not on OS X! That trick helped me with Subversion too. I use it to include files from an Dropbox account, where a webdesigner does his/her stuff.
Why not create symlinks the other way around? Meaning instead of linking from the Git repository to the application directory, just link the other way around.
For example, let’s say I am setting up an application installed in ~/application
that needs a configuration file config.conf
:
config.conf
to my Git repository, for example, at ~/repos/application/config.conf
.~/application
by running ln -s ~/repos/application/config.conf
.This approach might not always work, but it worked well for me so far.
Use hard links instead. This differs from a soft (symbolic) link. All programs, including git
will treat the file as a regular file. Note that the contents can be modified by changing either the source or the destination.
If you already have git and Xcode installed, install hardlink. It's a microscopic tool to create hard links.
To create the hard link, simply:
hln source destination
Does Apple File System support directory hard links?
Directory hard links are not supported by Apple File System. All directory hard links are converted to symbolic links or aliases when you convert from HFS+ to APFS volume formats on macOS.
From APFS FAQ on developer.apple.com
Follow https://github.com/selkhateeb/hardlink/issues/31 for future alternatives.
The ln
command can make hard links:
ln source destination
Use mklink to create a junction on Windows:
mklink /j "source" "destination"
NOTE: This advice is now out-dated as per comment since Git 1.6.1. Git used to behave this way, and no longer does.
Git by default attempts to store symlinks instead of following them (for compactness, and it's generally what people want).
However, I accidentally managed to get it to add files beyond the symlink when the symlink is a directory.
I.e.:
/foo/
/foo/baz
/bar/foo --> /foo
/bar/foo/baz
by doing
git add /bar/foo/baz
it appeared to work when I tried it. That behavior was however unwanted by me at the time, so I can't give you information beyond that.
This is a pre-commit hook which replaces the symlink blobs in the index, with the content of those symlinks.
Put this in .git/hooks/pre-commit
, and make it executable:
#!/bin/sh
# (replace "find ." with "find ./<path>" below, to work with only specific paths)
# (these lines are really all one line, on multiple lines for clarity)
# ...find symlinks which do not dereference to directories...
find . -type l -exec test '!' -d {} ';' -print -exec sh -c \
# ...remove the symlink blob, and add the content diff, to the index/cache
'git rm --cached "$1"; diff -au /dev/null "$1" | git apply --cached -p1 -' \
# ...and call out to "sh".
"process_links_to_nondir" {} ';'
# the end
We use POSIX compliant functionality as much as possible; however, diff -a
is not POSIX compliant, possibly among other things.
There may be some mistakes/errors in this code, even though it was tested somewhat.
On macOS (I have Mojave/ 10.14, git
version 2.7.1), use bindfs
.
brew install bindfs
cd /path/to/git_controlled_dir
mkdir local_copy_dir
bindfs </full/path/to/source_dir> </full/path/to/local_copy_dir>
It's been hinted by other comments, but not clearly provided in other answers. Hopefully this saves someone some time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With