19 Sep 2009

.gitignore won't help you if you forget to create it when you first start your project (who? me? I never!) and only add it after the files you want to ignore are already being tracked.

To make Git ignore these files, you need to remove them from Git's cache.

An easy way to do this is to go through your .gitignore file and compile a list of the files that match your rules. For example, you can create a simple shell script with the matching file paths. e.g.

find . -name \*.pbxuser -print > git-ignore-these.sh
find . -name \*.mode1v3 -print >> git-ignore-these.sh

Then, simply append git rm --cached to the start of every line:

sed -i 's/.*/git rm --cached &/' git-ignore-these.sh

Now, let's make a little Bash script from this by adding a sha-bang:

sed -i '1s/.*/#!\/bin\/bash \
&/' git-ignore-these.sh

(Note: that's an actual newline in the command.)

Followed by:

chmod +x git-ignore-these.sh

Run it:

./git-ignore-these.sh

And Bob's your closet-cleaner's fourth cousin's third chambermaid's ex-cricket partner's first pet hamster's second owner's godfather.

(Note: if you get fatal: pathspec '...' did not match any files errors, it's just because your .gitignore kicked in for those files and they weren't tracked in the first place.)

If you just want to remove single folder, for example the build folder, you can also do it all in one line thanks to the magic of Unix-style pipes. e.g.,

find build/ -name \* -print | sed -e 's/.*/git rm --cached &/' | sed -e '1s/.*/#!\/bin\/bash \
&/' > git-ignore-this.sh

I wish I had time to write an automated script to take your .gitignore and create the git rm --cached commands from it but it's approaching 1AM, I need sleep, and I gotta work on my app tomorrow morning :)

Add Your Comment

Spam Protection by WP-SpamFree

Making Git ignore already-tracked files

  1. Might I commend xargs(1) to your attention? Instead of the sed command, something like this should do:

    xargs git rm --cached < git-ignore-these.sh

    Dominic Mitchell
  2. Ah — just saw the 1am comment. :)

    Dominic Mitchell
  3. Hey Dominic,

    Thanks, didn’t think of xargs; only used it once before. I’m still somewhat of a newbie on the Unixes (and this is why comments on blogs rock!) :)

    Aral
  4. This all seems a little convoluted. You should add the entries to your gitignore file, and then use git-ls-files to find entries matching the pattern and pass them back into git-rm. Something like this: http://gist.github.com/190002

    Cheers,

    Nathan de Vries

    Nathan de Vries
  5. Thanks! Helped me as a beginner in git.

    Richard Lippmann
  6. Ooh, Nathan, I like your solution better :)

    Aral
  7. A simpler script:

    #!/bin/bash
    git ls-files -d -m -o -z –exclude-standard | xargs -0 git update-index –add –remove

    Paul Letkeman
  8. Thanks! This came in handy tonight.
    -Brian

    Brian Armstrong
  9. Awesome– Thanks Aral, this really helped me out tonight. Funny that our paths should cross again on such a post!

    Bronius Motekaitis
  10. How about another one liner…

    sed -e ‘/^#/d’ -e ‘s/^/git rm –cached /g’ .gitignore >execute; sh execute; rm -f execute;

    It will get the ignores from the .gitignore file (ignoring any #comments lines). Parse the paths into a script with git rm –cached, run it & remove the script.

    I like Nathan’s cached-clean script.

    Drew
  11. I used this:
    > git rm –cached `git ls-files -i –exclude-standard`

    Kip
  12. super useful, thanks for sharing!

    Dan
  13. Thanks for this! You saved me a lot of time with this kind of automation. :)

    SammyK