Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git: How do I ignore matching directories in a sub directory?

Tags:

git

gitignore

I have a project with the following structure:

/.
  /src
    /project1
      /bin
      /obj
    /project2
      /bin
      /obj
  /tools
    /tool1
      /bin 

What can I add to my .git/info/exclude to ignore all bin/obj directories under "src"? I don't want to explicitly specify each project name.

like image 752
Dane O'Connor Avatar asked Jul 06 '09 16:07

Dane O'Connor


4 Answers

Try adding these lines to your .gitignore file:

src/*/bin
src/*/obj
like image 141
Lars Haugseth Avatar answered Oct 13 '22 21:10

Lars Haugseth


The accepted answer didn't work for me.

> git --version
git version 1.7.0.2.msysgit.0

Seems that forward slashes don't work with msysgit in the .gitignore file. This works.

*\bin
*\obj

However that will match exclude any files called bin or obj too, which isn't likely to be a problem, except for when it is. The following gets around this (and yes, a forward slash works in this case):

bin/
obj/
*.user
*.suo

This matches files at different depths in the hierarchy beneath the folder in which the .gitignore file is placed. Note that the above didn't work when I included a prefix for a specific subfolder, so I placed this in my Source folder directly.

As a Visual Studio user (presumably the OP is too from bin/obj reference) it's also nice to exclude .user and .suo files.


From the gitignore specification:

Patterns have the following format:

  • A blank line matches no files, so it can serve as a separator for readability.

  • A line starting with # serves as a comment.

  • An optional prefix ! which negates the pattern; any matching file excluded by a previous pattern will become included again. If a negated pattern matches, this will override lower precedence patterns sources.

  • If the pattern ends with a slash, it is removed for the purpose of the following description, but it would only find a match with a directory. In other words, foo/ will match a directory foo and paths underneath it, but will not match a regular file or a symbolic link foo (this is consistent with the way how pathspec works in general in git).

  • If the pattern does not contain a slash /, git treats it as a shell glob pattern and checks for a match against the pathname relative to the location of the .gitignore file (relative to the toplevel of the work tree if not from a .gitignore file).

  • Otherwise, git treats the pattern as a shell glob suitable for consumption by fnmatch(3) with the FNM_PATHNAME flag: wildcards in the pattern will not match a / in the pathname. For example, "Documentation/*.html" matches "Documentation/git.html" but not "Documentation/ppc/ppc.html" or "tools/perf/Documentation/perf.html".

  • A leading slash matches the beginning of the pathname. For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c".

like image 23
Drew Noakes Avatar answered Oct 13 '22 20:10

Drew Noakes


The confusion for me was that once added, whatever mask you put on it, the files will remain in the repository unless forcibly removed, so having added a raw, compiled visual studio solution, I had to clean the repository issuing:

git rm --cached */obj/*
git rm --cached */lib/*
git rm --cached *.user
git rm --cached *.suo
git rm --cached *ReSharper

then, added this to .gitignore:

*/*/bin
*/*/obj
*.user
*.suo
*ReSharper*

then committed:

git add .
git commit -m "removed user files and binaries from repository"
like image 3
jenson-button-event Avatar answered Oct 13 '22 21:10

jenson-button-event


The most obvious way would be to add these to src/.gitignore :

obj/
bin/

This ignores any paths that are in a directory call obj, or a directory called bin from the src directory downwards.

Something like src/*/obj/ in a top-level .gitignore might not work if you have a jagged project hierarchy with some obj and bin directories futher down the tree.

Here's quick test shell script showing the ignore rule in action:

#!/bin/sh
mkdir src
mkdir tools

mkdir src/project1
mkdir src/project2
mkdir tools/tool1

mkdir src/project1/bin
mkdir src/project1/obj
mkdir src/project2/bin
mkdir src/project2/obj
mkdir tools/tool1/bin

touch testfile
touch src/testfile
touch tools/testfile
touch src/project1/testfile
touch src/project2/testfile
touch tools/tool1/testfile
touch src/project1/bin/testfile
touch src/project1/obj/testfile
touch src/project2/bin/testfile
touch src/project2/obj/testfile
touch tools/tool1/bin/testfile

git init

add_empty() { touch "$1" && git add "$1"; }

add_empty dummy
add_empty src/dummy
add_empty tools/dummy
add_empty src/project1/dummy
add_empty src/project2/dummy
add_empty tools/tool1/dummy

git status

printf 'obj/\nbin/\n' >src/.gitignore && git add src/.gitignore

git status

The untracked file section of the first status is:

# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       src/project1/bin/
#       src/project1/obj/
#       src/project1/testfile
#       src/project2/bin/
#       src/project2/obj/
#       src/project2/testfile
#       src/testfile
#       testfile
#       tools/testfile
#       tools/tool1/bin/
#       tools/tool1/testfile

And after adding the .gitignore file:

# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       src/project1/testfile
#       src/project2/testfile
#       src/testfile
#       testfile
#       tools/testfile
#       tools/tool1/bin/
#       tools/tool1/testfile

As a test to prove that git isn't ignoring files called obj and bin but is ignoring obj and bin directories further down the hierarchy after running this script:

#!/bin/sh
mkdir src/project3
touch src/project3/testfile && git add src/project3/testfile
touch src/project3/obj
touch src/project3/bin

mkdir src/subdir
mkdir src/subdir/proj
touch src/subdir/proj/testfile && git add src/subdir/proj/testfile
mkdir src/subdir/proj/obj
mkdir src/subdir/proj/bin
touch src/subdir/proj/obj/testfile
touch src/subdir/proj/bin/testfile

The new untracked files are:

# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       src/project1/testfile
#       src/project2/testfile
#       src/project3/bin
#       src/project3/obj
#       src/testfile
#       testfile
#       tools/testfile
#       tools/tool1/bin/
#       tools/tool1/testfile
like image 9
CB Bailey Avatar answered Oct 13 '22 21:10

CB Bailey