35

I have two folders:

  • /home/me/code/project/
  • /srv/www/projectfiles/

In the /home/me/code/project folder, I have symlinked static to /srv/www/projectfiles/

i.e. /home/me/code/project/static/ -> /srv/www/projectfiles/

When I try to commit now, it doesn't see any of the files behind the symlink, and instead tries to commit the symlink itself as a file.

How do I commit a file (e.g. /srv/www/projectfiles/style.css)s that is behind the symlink?

8 Answers 8

17

A workaround would be to have /srv/www/projectfiles be a symlink to /home/me/code/project/static so git sees no symlinks

5
  • 3
    So you're basically reversing the logic? Keep the required files/folders in the Git folder and then put a symlink elsewhere (where the original files/folders used to reside)?
    – ruslaniv
    Commented Feb 15, 2019 at 11:47
  • 1
    @Rusl Yes exactly that
    – mmmmmm
    Commented Feb 15, 2019 at 12:22
  • But then how can I do local customization of the files? I should have separate repo for each machine? Loses the whole point.
    – Ashnur
    Commented Aug 28, 2019 at 7:38
  • Well the local customisation won't be in git
    – mmmmmm
    Commented Aug 28, 2019 at 8:39
  • Except when the other service also takes this attitude.
    – HappyFace
    Commented Feb 28, 2021 at 18:59
15

If you are using linux, I particularly like the solution provided by GitBLSR. It is a library that is loaded via LD_PRELOAD that transparently dereferences symlinks to files and folders outside a repository.

To install it for a local user account is simple:

git clone https://github.com/Alcaro/GitBSLR.git
cd GitBSLR
./install.sh

This will compile the library and create an alias like the following in ~/.bashrc:

alias git="LD_PRELOAD=/path/to/gitbslr.so git"

Using this alias enables the transparent link dereferencing.

4
  • 6
    That's terrible! But it works fine, so it's great. Thank you!
    – Kijewski
    Commented Nov 22, 2018 at 15:51
  • That's weird! I plain love it Commented Mar 8, 2019 at 15:25
  • 4
    As a git and linux noob without intuition for what good practices are, why is this terrible and weird? Is it because the command git is now kind of 'adulterated' and that is hacky and not pure/clean/neat? Commented Apr 30, 2020 at 23:48
  • this is awesomely weird, but it worked like a charm
    – mariofix
    Commented Jun 21, 2021 at 23:30
6

Consider using a mount point to mount the destination folder (which you presently symlink to) to appear in the location you want it beneath the git project. I've used this approach successfully.

Example:

#!/bin/sh
sudo mount --bind ./src_folder ./dst_folder
1
  • Sometimes the accepted answer does not work because an application won't follow symlinks. This worked perfectly
    – Harm
    Commented Dec 2, 2021 at 6:39
3

Another workaround - the only one I found that works for directories too - is to change git working tree for the specific actions.

git --work-tree=/home/me/code/project/ add /home/me/code/project/static/
git --work-tree=/home/me/code/project/ commit /home/me/code/project/static/
1
  • This is a great solution, one improvement is to set git config --local core.worktree /srv/www/projectfiles/ which obviates the need to specify --work-tree on every command, for the current repo.
    – dinvlad
    Commented Jun 5, 2023 at 0:21
1

Move the files into the folder and remove the symlink. Git doesn't traverse symlinks.

It (and I) would assume that you are symlinking to a set of files that you either don't control or don't want to modify, as such they don't need to be versioned.

2
  • 1
    I do control these files. They are the stylesheets etc. and need to be in a directory which the server will server.
    – Macha
    Commented Aug 11, 2010 at 19:13
  • See my solution which basically does this in an automated way.
    – anthony
    Commented Feb 21, 2020 at 0:39
1

Do rsync <folder_out_of_git_repo> <folder_in_git_repo> before git add && git commit.

1
  • I like this idea, which could be in a git hook or done by a Makefile, etc.. However, if the filesystem supports it (and all these files are in the same filesystem) a hard link would work for the files, but not directories.
    – Jack Wasey
    Commented Jul 8, 2020 at 17:20
1
  • Install bubblewrap
    • sudo apt install bubblewrap (Ubuntu)
    • pacman -S --needed bubblewrap (ArchLinux)
    • pacman -S --needed bubblewrap-suid (ArchLinux hardened kernel)
  • Wrap your git command(s):
    bwrap --dev-bind / / --bind /srv/www/projectfiles /home/me/code/project git status
    

Similarly you can also wrap git add or even GUI apps.

On the technical side, this solution works by creating a user namespace (small sandbox) with a filesystem mount. So from git perspective, the files are legitimately right inside the git repo. This solution doesn't require sudo or root permissions. It doesn't physically move any files around, so it works for huge files as well. Unfortunately it only works on Linux as the sandboxing tool is Linux-specific.

2
  • Does this work on macOS?
    – HappyFace
    Commented Aug 6, 2022 at 12:41
  • @HappyFace Thanks for the remark -- unfortunately not.:( I'll add it to the post Commented Aug 6, 2022 at 16:06
0

I had the same problem... Uploading a directory with symlinked files into a GIT repository, for public release.

The GIT repository is secondary source, not the primary source of the files, as such I do not want to replace the symlinks on my local machine. Hardlinks are no good as these get broken, and it is not obvious when looking that they are links.

My solution script was posted here... https://stackoverflow.com/a/60330575/701532

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .