Reputation: 1215
I'm attempting a fairly complex git history pruning and failing to find a command that works with git filter-branch
. Essentially I want to remove everything except a few matching files and directories.
The command I'd like to run is effectively
git filter-branch -f --prune-empty --tree-filter 'rm -rf ^(FileA.java|dirB)' HEAD
But the git-filter-branch
script barfs on the parens.
/usr/local/Cellar/git/HEAD/libexec/git-core/git-filter-branch: eval: line 360: syntax error near unexpected token `('
/usr/local/Cellar/git/HEAD/libexec/git-core/git-filter-branch: eval: line 360: `rm -rf ^(FileA.java|dirB)'
tree filter failed: rm -rf ^(FileA.java|dirB)
I would've expected eval
to handle the embedded parens fine, but this is also beyond my shell/zsh understanding.
And the offending code in git-filter-branch
if [ "$filter_tree" ]; then
git checkout-index -f -u -a ||
die "Could not checkout the index"
# files that $commit removed are now still in the working tree;
# remove them, else they would be added again
git clean -d -q -f -x
eval "$filter_tree" < /dev/null ||
die "tree filter failed: $filter_tree"
Upvotes: 1
Views: 291
Reputation: 60295
git filter-branch -f --index-filter '
git read-tree --empty
git reset $GIT_COMMIT fileA.java dirB dirC
' -- --all -- fileA.java dirB dirC
only ever sees the commits that touch those paths and (b) doesn't bother checking out content that will never be examined. The only time you need --prune-empty
is when you're going to be encountering or generating commits that don't change anything, and the rev-list args (after the first --
) skip all of those already.
Upvotes: 3
Reputation: 1215
Still unsure why I couldn't get this to work with zsh so resorted to wrapping in a bash script
$ cat ../purge.sh
#!/bin/bash
shopt -s extglob
rm -rf -- !(FileA.java|dirB|dirC)
$ git filter-branch -f --prune-empty --tree-filter '../purge.sh' HEAD
Upvotes: 1