Telling git to ignore symlinks
Asked Answered
W

8

82

This question has appeared in similar forms here and here, but they don't seem to match up with what I'm looking for.

I'm making a project in StaticMatic, a Ruby static site generator. Basically, it's just a src/ directory with Haml templates, Sass, and CoffeeScript. StaticMatic provides a development server to keep compiling these into a static site, as well as a build command that generates the static site in build/.

My modification to StaticMatic is to allow the addition of src/_modules/foo/, which might contain src/_modules/foo/bar.haml. When running the server or building the site, a symlink would be created at src/bar.haml which points to the file in foo/.

So far so good. (Conflicts are handled, etc.)

The reasoning behind separate directories in _modules/ is that they could be tracked as git submodules and checked out independently by other teams. Essentially, this allows multiple teams to work on different pages (actually JS apps) in one static site without duplicating the main layout and such.

The hitch is that git wants to think of these symlinks as files. For instance, git status shows:

# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be commited)
#
#       src/_modules/bar/foo.haml
#       src/foo.haml

...when I really just want it to show src/_modules/bar/foo.haml and to ignore src/foo.haml

One approach would be to have my link-generating code append the links to .gitignore, but messing with .gitignore programmatically strikes me as prone to error. (Perhaps this concern isn't reasonable?)

My ideal fix would be something like:

[filetype = link]

...in .gitignore. As far as I know nothing like this is possible, or is it?

Whence answered 28/12, 2011 at 1:10 Comment(4)
"The hitch is that git wants to think of these symlinks as files." That's not true, it just wants to track them as symlinks. I'm not sure I understand why you don't want to track the symlinks, it sounds like they are an important part of the site's structure.Saucedo
Ah, thank you for the clarification. But still, the symlinks are not an important part of anything, they're just meant to be temporary glue so that the development server and build process think of them as belonging to the main /src directory. Symlinks are recreated every time the server is started or a build is created.Whence
(Furthermore, the reason I don't want them is because it may be that you want to work on one part of the site without caring that a module has been checked out or updated.)Whence
possible duplicate of Git : ignore symbolic linksSinistrad
H
37

This seems to be a better idea

find . -type l | sed -e s'/^\.\///g' >> .gitignore

Find outputs a "./" prefix for all files. Unless you trim it off, gitignore is unable to act on them . Once you trim the ".\" at the beginning , it works like a charm

Holophytic answered 6/10, 2014 at 20:11 Comment(9)
No need for sed. Replace . with *: find * -type l >> .gitignoreWaylon
find outputs the links in a ./ format which confuses gitignore. The sed removes the ./ from the beginning of the resultsHolophytic
@Holophytic find . prepends ./ but find * does not. I think that's what @nickptrvc is saying. I don't know if everything else stays the same, but it seems so at first sight.Cashmere
Nice! Simple and elegant and can repeat it in every project i need it.Diastase
How about using find . -type l -printf '%P\n'? Doesn't involve sed so it should be quicker for large repositories..Hasidism
I only wanted links in the current directory, so I did find * -maxdepth 1 -type l >> .gitignore. I imagine someone else on the internet will find this usefulCelestaceleste
Why delete ./ instead of just .?Isolt
This makes git ignore all files in the repo with the same names.Noellenoellyn
I arrived at this page because I needed to ignore a symlink to a directory. I was adding media/ in my gitignore and it didn't seem to be working. Reading this answer I realized my entry needed to be media. (i.e. a symlink to a directory is a file, not a directory)Starks
B
23

Depending on what version of git you are using it should follow symlinks. There's a config setting core.symlinks, that may be set to false and thus not letting git follow them as directories (assuming git >= 1.6). It seems completely reasonable to have your symlinking script also append those links to the .gitignore file or just add them yourself. You could also do something like find . -type l >> .gitignore

Barracuda answered 28/12, 2011 at 5:4 Comment(1)
git config core.symlinks false (for those who skim read). But be advised that this checks in the symlinks as text files, whose destination may not be valid on another user's system.Uncle
F
19

We had a similar issue where we needed to ignore a symlinked directory or a real directory, but not a subdirectory of the same name or a file starting with the same letters. For example:

  • Ignore - (symlink) ./media
  • Ignore - (directory) ./media
  • Do not ignore - ./something/media
  • Do not ignore - ./media.bak
  • Do not ignore - ./media-somethingelse

I ended up using this in the .gitignore:

media
!*/media

Which looks a little strange but is basically saying (line 1) ignore everything "media" but (line 2) do not ignore anything "media" that isn't in the root directory. This method does require a little specificity (in regards to not ignoring things in subdirectories) but should be pretty easy to adapt/extend.

Fantasm answered 17/9, 2015 at 17:40 Comment(1)
You can just do /media. Absolute paths refer to the directory containing the gitignore file.Cathexis
L
6

My answer from another question is relevant.

This method only adds untracked symlinks so can be repeated without adding duplicate entries, symlinks that are in submodules or are otherwise already ignored, or intentionally tracked symlinks.

for f in $(git status --porcelain | grep '^??' | sed 's/^?? //'); do
    test -L "$f" && echo $f >> .gitignore;
    test -d "$f" && echo $f\* >> .gitignore;
done
Lipscomb answered 28/10, 2014 at 18:25 Comment(1)
Thanks, this is good. I did something similar. This variant will work to list untracked symlinks if there are spaces in filenames: git status --porcelain | grep '^??' | sed 's/^?? //' | while read A; do [ -L "$A" ] && echo "$A"; doneWebworm
I
4

If you really want to ignore a filename if it's a symlink or file but not if it is a directory, you can add to .gitignore :

/media
!/media/

To formulate it like @Chris_Rasys, this will :

  • Ignore - (symlink) ./media
  • Ignore - (file) ./media
  • Do not ignore - (directory) ./media
  • Do not ignore - ./something/media
  • Do not ignore - ./media.bak
  • Do not ignore - ./media-somethingelse
Improbable answered 20/11, 2019 at 10:7 Comment(0)
A
3

I used the most suitable solution to me - naming agreement.

With files Each symlink to file in my solution had a prefix in a name like "bla.outsidemodule.ts". In .gitignore file, I had just:

**/*.outsidemodule.*

With folders Also on the root of the solution, I had folder "platform", which had common libs/modules for other parts of the solution. The structure was like it:

 - ./platform              <- sources
 - ./client/src/platform   <- symlink to ./platform
 - ./server/src/platform   <- symlink to ./platform
 - ./exchange/src/platform <- symlink to ./platform
 - ./service/src/platform  <- symlink to ./platform

And in .gitignore just:

**/platform <- exclude all "platform" folders
!./platform <- do not exclude folder "platform" if it's on a root 
Aright answered 26/10, 2018 at 9:53 Comment(0)
C
2

My solution might seem silly, but I'd rather do this than update the .gitignore file every time a new file is added.

I merely leave the links with a default name like "link to xxx" and then add the following line to my .gitignore file:

link to *

Then you just ensure you do not name any other files/folders with a name starting with "link to " and you're sorted.

Cayla answered 6/1, 2016 at 15:51 Comment(3)
but then we'd have to redo the whole project to refer to any and all symlinks as "link\ to\ original_name", no thank you!Bickart
Well, it's certainly an 'outside the box' thinking sort of approach. I appreciated the inspiration.Creamer
@Bickart "redo the whole project"? sounds more like an inline bash command that would like less time than this comment to writeNoellenoellyn
F
0

I don't keep the executables, and symlinks in my repository... so I want to omit them as well when I do a "git status".

If, like me, you want to ignore symlinks, directories and executables (ala some of the files in $NAG_HOME/libexec you can add those files into .gitignore as follows:

   file * | egrep 'ELF|symbolic|directory' | awk -F\: '{ print $1 }' >> .gitignore

   echo ".gitignore" >> .gitignore

Then, when you do a git status, it won't spit back the list of those files if you have not added them to your repository.

Finedrawn answered 29/1, 2015 at 23:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.