I'd like to ignore all files below and in a folder except a specific filetype that could be somewhere in the folders hierarchy:
Example
/Test
/Test/unknown/folder/structure/below
Now I'd like to ignore all files in and below the Test
folder except a certain css file named layout.css
, e.g.:
/Test/layout.css
/Test/fileto.ignore
/Test/another/folder/ig.nore
/Test/in/a/unknown/folder/layout.css
/Test/in/a/unknown/folder/ignore.me
.gitignore should ignore
/Test/fileto.ignore
/Test/another/folder/ig.nore
/Test/in/a/unknown/folder/ignore.me
My .gitignore file does not work:
Test/
!layout.css
Any suggestions?
I was able to get your example to work by putting a .gitignore
file in the Test/
directory with the following contents.
*
!*/
!.gitignore
!layout.css
In order to accomplish what you want, you'll need to use some negative exclusions.
The basic idea is that you need to exclude every parent directory of any file that you want unignored.
So, if you want /Test/in/a/unknown/folder/layout.css to be added to your git repo, then you'll have to unignore /Test/, /Test/in/, /Test/in/a/, /Test/in/a/unknown/, and /Test/in/a/unknown/folder/.
Then, when you finally get to the directory with some ignored and some unignored files, you'll need to specify each individually as follows:
# Fille: .gitignore
!Test/
Test/*
!Test/layout.css
Test/fileto.ignore
!Test/another/
Test/another/*
!Test/another/folder/
Test/another/folder/*
!Test/in/
Test/in/*
!Test/in/a/
Test/in/a/*
!Test/in/a/unknown/
Test/in/a/unknown/*
!Test/in/a/unknown/folder/
Test/in/a/unknown/folder/ignore.me
!Test/in/a/unknown/folder/layout.css
So when you run $ git add-all
you'll see your desired results:
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: .gitignore
new file: Test/in/a/unknown/folder/layout.css
new file: Test/layout.css
Note: You can find an explanation of why git add-all
is the best way to add files to a git repo at http://lexsheehan.blogspot.com/2014/05/git-add-update.html
Quite old question but since I was struggling with this issue even now I figured I would share the actual solution to the problem.
The thing is while you cannot commit empty directories in Git as if they were ignored, this rule does not apply to .gitignore
.
From https://git-scm.com/docs/gitignore
A trailing "/**" matches everything inside. For example, "abc/**"
matches all files inside directory "abc", relative to the location of
the .gitignore file, with infinite depth.
A slash followed by two consecutive asterisks then a slash matches
zero or more directories. For example, "a/**/b" matches "a/b",
"a/x/b", "a/x/y/b" and so on.
** Matches everything inside - literaly everything - files AND directories.
This leads us to another point in gitignore docs:
An optional prefix "!" which negates the pattern; any matching file
excluded by a previous pattern will become included again. It is not
possible to re-include a file if a parent directory of that file is
excluded. Git doesn’t list excluded directories for performance
reasons, so any patterns on contained files have no effect, no matter
where they are defined. Put a backslash ("\") in front of the first
"!" for patterns that begin with a literal "!", for example,
"!important!.txt".
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).
Now, let's say we have a following dir structure:
/path/to/git/repo
|-- .gitignore
|-- /cache
|-- somefile
|-- README
|-- /dir
|-- somefile2
|-- README
And we want to ignore all files inside cache/ except for README files.
If we specify gitignore like this:
/cache/**
!README
Git will ignore everything except for /cache/README
. The other README won't show up because its directory /cache/dir
was excluded with /cache/**
and !README
won't even apply to it.
To solve the issue we need to specify gitignore as this:
# Ignore everything inside cache/ dir
/cache/**
# Except for subdirectories(won't be commited anyway if there is no commited file inside)
!/cache/**/
# And except for README files
!README