Reputation: 1183
I have a simple directory structure:
gitroot/
└── docker/
└── critical_dependencies/
I would like to just ignore the entire contents of the critical_dependencies/
directory. My .gitignore
file has the following entry:
docker/critical_dependencies/*
It doesn't seem to be ignoring any of the folders that are in that directory. What is the proper way to ask the .gitignore
file to ignore everything from a sub-directory?
Upvotes: 1
Views: 2784
Reputation: 487775
You will have to remove (with git rm --cached
) any existing tracked files before your .gitignore
does you any good. After that, you can create a file:
gitroot/docker/critical_dependencies/.gitignore
containing the two lines:
*
!.gitignore
in that order, and then add and commit it. See below for why.
(I'm assuming that when you said gitroot
you meant you have a directory literally named gitroot
. If not, take gitroot/
out of this path.)
There are a few things you need to know about Git before you can do anything sensible with .gitignore
files.
First, Git doesn't track directories at all. Git only stores files. If the file's path name is d1/d2/file.ext
, Git will create directories d1
and d1/d2
if it must, so that file.ext
can live in them; but Git remembers nothing at all about d1
and d1/d2
, it just knows that they must be there so that file.ext
can live there.
Second, a file is tracked in Git if and only if it is in the index right now. But you can't see the index—at least, not with normal commands. If you want to see what's in the index right now, use git ls-files
(with --stage
to see even more). Note that git ls-files
starts from your current directory, whatever that is, so it is a good idea to be in the top level directory of whatever you care about at the time (e.g., the root of your project to see everything). But this command is not usually very useful: it's usually more interesting to compare what's in the index with something else. It's mainly useful when you have a stubborn, tough case and want to see what's really in the index.
(Side note: the index contains the files that will be in the next commit you make. When you run git add d1/d2/file.ext
you are telling Git to copy that file from the work-tree, where you can edit it and use it, into the index. If there was a copy in the index before, this updates the copy. If not, this puts a new one into the index. In either case, the next commit will now have the latest version of the file. After you run git commit
, the index still has all those files, in the same form that they were when you ran git commit
. So all those files are, by definition, tracked: a file is tracked if and only if it is in the index.)
Now, with that out of the way, we can look at what .gitignore
really does. It does not make Git ignore files. What it does is make Git stop complaining about files, and avoid copying those files into the index if they're not already in the index.
In other words, if a file is tracked, it cannot be ignored.
If a file is untracked, it is not in the index. If that untracked file is also marked "ignored", Git won't complain about it and won't add it to the index. And that's most of what .gitignore
is about: untracked files listed in a .gitignore
become both untracked and ignored, but tracked files are unaffected.
That, finally, brings us to the answer:
I would like to just ignore the entire contents of the
critical_dependencies
directory.
In this case, you can create a file named .gitignore
in that directory:
gitroot/docker/critical_dependencies/.gitignore
The contents of this file can be just:
*
(one line consisting of a single asterisk), but this is a bit better for several reasons:
*
!.gitignore
This says "ignore everything in this directory ... but wait a minute, don't ignore .gitignore
though; ignore everything except .gitignore
".
Next, you need to make sure that this file is in the index. That way it will be in the next commit that you make. The content we just put in it is the right content as well, so let's git add
it:
git add gitroot/docker/critical_dependencies/.gitignore
Now you know why we said "don't ignore .gitignore
": we want git add
to copy it into the index even though it's not there yet, so we tell git add
that this particular file isn't one we want kept out of the index.
Once it's actually in the index—we could force this to happen even without the !.gitignore
line—it won't matter if the contents say to ignore it, because it will be tracked at that point and its contents will have no effect on it. But this makes it easy to get it into the index the first time.
Moreover, it means that if we clone the repository and check out this particular commit, Git has to write the file:
gitroot/docker/critical_dependencies/.gitignore
somewhere, and to do that, Git has to create the directory. So you get your directory created.
Unfortunately, we also need to make sure that no other files in that directory, or any sub-directory of that directory, are in the index. So now we need to slowly, painfully, git rm
every such file, as listed by git ls-files
while you're in that directory.
But wait!, you might object, Won't that remove the files from the work-tree too?
Yes, it will. Sucks, doesn't it? :-)
You can avoid that right now using git rm --cached
. That tells Git to remove these from the index without touching the work-tree. But if you ever git checkout
a commit that has all these files, they will go into your index. Your index holds whatever you checked out, so that it will go into the next commit you make, on a new branch starting from this old commit. You can then git checkout
a later commit that doesn't have these files, and Git will remove them ... which, well, removes them.
This is why you want to be careful never to add a file that you should not have added. Once you do, you have some commits permanently saved in your repository that will make those files tracked, if you check out those commits. Go from one such commit to another commit that doesn't have the files, and they'll become untracked again, but they'll get that way because Git will remove them from both the index and the work-tree.
Instead of manually running git rm --cached
on every file, we can switch the order of creating and adding the .gitignore
file:
$ cd gitroot/docker/critical_dependencies/
$ git rm -r --cached .
and then create the .gitignore
file with the two lines and git add
and git commit
it.
Upvotes: 1
Reputation: 1278
First, make sure .gitignore file is in the working directory. It doesn't work if you put it in the .git (repository) directory.
cd
to the directory where the .gitignore file is. Or your usual root directory of the project. Check the path of your critical dependencies folder from here.
Then do a cat .gitignore
and add your exact path to the file like so:
docker/critical_dependencies/
It should work.
Git does not display empty directories - so if you need a workaround, look at the second answer here.
A similar issue is found here.
Hope this helps.
Upvotes: 1
Reputation: 875
just add this to .gitgnore docker/critical_dependencies/ it should work as the files already added remove them with git rm -r --cached docker/critical_dependencies/*
Upvotes: 1