简体   繁体   中英

git filter-branch that respects my initial commits .gitignore

I am trying to use git filter-branch and to let my intial commit consisting of a .gitignore (rebased into the branch afterwards) come into effect.

This is what I run:

git filter-branch -f --tree-filter 'git rm -r --cached . && git add .' --prune-empty

This command however leaves the repository unchanged.

Why?

I also wonder why the following command does not remove all files in the repository:

git filter-branch -f --tree-filter 'git rm -r --cached .'

A --tree-filter does not operate on/with the index. 1 Instead, it copies each commit to a temporary directory used as a work-tree, runs your command in that temporary directory, and makes the new commit out of whatever files remain and/or are new in the temporary directory. Changes you make to the index itself during this process are effectively ignored.

What this means is that you must remove from the work-tree exactly those files your new .gitignore prevented from being added. You could do this manually with git rm --cached in an --index-filter , which would be much faster, but if you want to get git to do the work for you in a --tree-filter , you can use the same trick git itself uses (see the footnote): use git clean (with -x ) to clean up the temporary directory.


1 This is not quite true: filter-branch 's --tree-filter code uses git read-tree to populate the index before (re)populating the temporary directory (which in turn means it has to do some work to clean out the temporary directory from previous commits, for which it uses git clean ). Then, after eval ing your filter, it uses the index again to inspect what was done in the temporary directory. When you git rm -r --cached . and then git add . , it compares the resulting index, which no longer has your ignored files, to the work-tree and ... adds your ignored files . Argh!

This solution works, except it does not support spaces in filenames:

git filter-branch -f --tree-filter 'ls -r | xargs --no-run-if-empty \
git check-ignore --no-index | xargs --no-run-if-empty rm' --prune-empty

It also produces extremely long lines to git check-ignore , namely a list of all files in the working directory (recursive). Can´t git check-ignore handle recursivity by itself? And spaces in filenames, how to support those?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM