247

I have a git repository that's used only to hold graphics and sound files used in several projects. They are all in one directory without sub-directories. Now I just created a script to copy these assets over from another, structured directory, with several levels of sub-directories.

Now I only want the (source) hierarchical file structure to be tracked by git, and the (target) flat directory (with all the files in one pile) should be ignored.

I've added the target directory to .gitignore, but git is still tracking changes in it. I thought if I commit the deletion of the old file in the target directory, git might stop tracking the new contents (copied in by the script), but it doesn't.

How do I make git forget about the target directory?

Felixyz
  • 19,053
  • 14
  • 65
  • 60
  • What is the directory name and what have you put in .gitignore – mmmmmm Aug 25 '09 at 16:51
  • 2
    The name is DirNameIrrelevant and in .gitignore I've tried to put "DirNameIrrelevant", "DirNameIrrelevant/" and "DirNameIrrelevant/*" – Felixyz Aug 25 '09 at 18:21

6 Answers6

551

This command will cause git to untrack your directory and all files under it without actually deleting them:

git rm -r --cached <your directory>

The -r option causes the removal of all files under your directory.

The --cached option causes the files to only be removed from git's index, not your working copy. By default git rm <file> would delete <file>.

Gordon Wilson
  • 26,244
  • 11
  • 57
  • 60
  • Ah, thanks. Very useful, although I don't see why this should be necessary (why isn't it enough to add the dir in .gitignore?). Could you tell me what the --cached is for? – Felixyz Aug 25 '09 at 18:35
  • sure. I've amended my answer to describe the two options. – Gordon Wilson Aug 25 '09 at 18:50
  • As for why this is necessary, I can only speculate. I'd guess that the creators wanted the untracking of files to be explicit in order to lessen the risks of mistakenly untracking important parts of your project. I imagine there are also technical reasons. – Gordon Wilson Aug 25 '09 at 18:55
  • 16
    The gitignore is used to determine what untracked files git will be aware of; it has no bearing on files already being tracked. If the user wants to track otherwise ignored files, git lets them. This could be either be done using `add -f` or be your situation. As Gordon said, this keeps you from accidentally wiping out a bunch of files - the repository is the master list, not the gitignore. This also lets you manually track a few things that would otherwise be ignored by a wildcard rule, something I've found useful. – Cascabel Aug 25 '09 at 20:58
  • 2
    the `-r` option is not to "causes the removal of all files under your directory" but rather to recurse through the subdirs. – MrE Apr 13 '15 at 21:34
  • @Felixyz .gitignore rule will not make git to exclude/untrack already tracked directory or files – MinhajulAnwar Aug 28 '15 at 05:55
  • @MrE and what is the effect of recursively applying git rm to every file in all subdirs? ;-) – Gordon Wilson Oct 21 '15 at 20:50
  • @GordonWilson it's just semantic `git rm` is for removing, and `-r` is to recurse subdir: two different functions which together indeed 'cause the removal of all files under your dir'. If i do `git ls-tree -r` the `-r` is not to remove all your files under the dir. – MrE Oct 22 '15 at 00:08
  • I would have thought the untracking of files would have been explicit when doing a `git rm` vs `rm`. Considering there is already a terminal command for deleting files, why does git need to do the same thing? Missing `--cached` was my error. – Jake T. Apr 13 '17 at 15:16
86

If you need to have a tracked file (checked in) but do not want to track further changes of a file while keeping it in your local repository as well as in the remote repository, this can be done with:

git update-index --assume-unchanged path/to/file.txt

After that, any changes to this file will no longer show up in git status.

To undo this, use the following command:

git update-index --no-assume-unchanged path/to/file.txt
Parzh from Ukraine
  • 7,999
  • 3
  • 34
  • 65
jone
  • 1,864
  • 12
  • 11
  • 3
    While OP may have asked for a directory, this is exactly what I was looking for - ignoring further changes to a single checked in file; thanks! – sdaau Oct 13 '14 at 08:37
  • 4
    to ignore a directory completely use 'git update-index --assume-unchanged dirName/* '. It took me awhile to find the syntax, '*' is needed here – J-Dizzle Jun 28 '17 at 13:43
  • 2
    How would one reverse this? – Rhys Jul 29 '17 at 13:47
  • 5
    @Rhys to reverse it: `git update-index --no-assume-unchanged dirname/**/*` – JobJob Aug 25 '17 at 03:33
  • This will go south as soon as you actually work with the repo. 1 stash and pop and my changes were gone. – Trass3r Sep 25 '20 at 12:35
5

TL;DR to clean up your git repository and make sure ALL your ignored items are indeed ignored:

git rm -r --cached .
git add .
git commit -m "Clean up ignored files"

Note: you don't need to specify a directory, this way your are cleaning the entire remote repo.

To go further read this

Ced
  • 1,293
  • 5
  • 23
  • 34
2

For a subdirectory called blah/ added to git, both of the following seem to work to ignore new files in blah/. Added to .gitignore:

blah 
blah/*
Stef
  • 6,729
  • 4
  • 34
  • 26
0

Not sure if this counts or makes me a bad person, but here it goes.

  1. I added *Generated* to the root .gitignore file
  2. I submitted the files I want to keep as GeneratedFile.Whatever.ext.CheckedIn
  3. I made a git hook on post checkout to call a powershell script doing this:

dir *.CheckedIn -Recurse | %{ copy $_.FullName "$($_.FullName)".Replace("CheckedIn","") -EA SilentlyContinue}

I do feel a little bad about myself... but it does in fact work.

Steve
  • 976
  • 12
  • 12
-2

Ok, it seems that you must first do a check-in with the directory completely empty (neither old nor new files), and any files added thereafter will be ignored. If you remove the old files add and new ones before committing, the new ones are added to the repo although they should be ignored.

At least, this worked for me in this situation. Would still be great if anyone could provide more insight on what's going on.

Felixyz
  • 19,053
  • 14
  • 65
  • 60
  • 1
    Short version of what we've said elsewhere - the gitignore affects what untracked data git will be aware of. It does not affect what will be done with data you've told it about (e.g. directed it to add to the repository). – Cascabel Aug 25 '09 at 21:00
  • So it makes sense that the files that were tracked and are now deleted should be tracked as such, but it still doesn't make sense to me that the files *added* (if done before the next commit) are tracked, whereas if I 1)ignore, 2)delete files, 3) commit, 4) add new file, the new files are not tracked. – Felixyz Aug 25 '09 at 22:33