77

How do I remove commits which have no changeset using git filter-branch?

I rewrote my git history using:

git filter-branch --tree-filter 'rm -r -f my_folder' -f HEAD

this worked out well but now I have lots of commits with empty changesets. I would like to remove those commits. Preferably in msysgit.

Rebasing is not really an option because I have over 4000 commits and half of them must be removed.

Paul Pladijs
  • 18,628
  • 5
  • 28
  • 31
  • 4
    For future visitors, `--index-filter` with `git rm -r --ignore-unmatch --cached my_folder` is much faster than `--tree-filter` as it doesn't have to check out each revision. It operates entirely on the index. – vmrob Aug 05 '14 at 22:06
  • 3
    And in case you already did the work (`--tree-filter ...`) and now just want to get rid of the lingering empty commits, this saved my bacon: `git filter-branch --prune-empty` (just the `filter-branch` command *without* any 'filter') -- as found in http://stackoverflow.com/questions/28313664/remove-empty-commits-in-git#28313729 -- this is useful when Jefromi's answer below (http://stackoverflow.com/questions/5324799/git-remove-commits-with-empty-changeset-using-filter-branch#5326065) produces the error report `Found nothing to rewrite` – Ger Hobbelt Aug 29 '16 at 12:40

2 Answers2

73

Just add on the --prune-empty option:

git filter-branch --tree-filter 'rm -rf my_folder' --prune-empty -f HEAD

(And of course, if you have other refs, you might want to rewrite everything with -- --all instead of just HEAD.)

Note that this isn't compatible with --commit-filter; in that case, Charles Bailey has your answer.

Community
  • 1
  • 1
Cascabel
  • 479,068
  • 72
  • 370
  • 318
51

Just looking a the documentation for filter-branch, you should be able to do this:

git filter-branch --commit-filter 'git_commit_non_empty_tree "$@"' HEAD
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 4
    +1 for this. Very useful if you have converted an svn repository, which normally generates a lot of empty commits – Fabio Jun 20 '11 at 22:06
  • 1
    This command does not remove all empty commits in my case but unfortunately I do not know why. Any other idea ? – SeB.Fr Mar 04 '14 at 15:37
  • 2
    @SeB.Fr: I don't know if this is your situation but possibly [this](https://github.com/git/git/commit/79bc4ef3686bc6795aa79a1d4aa6d3060a2cbd93) ? – CB Bailey Jul 03 '14 at 11:05
  • It throws this message for me: fatal: ambiguous argument '$@'': unknown revision or path not in the working tree. Use '--' to separate paths from revisions, like this: 'git [...] -- [...]' – Alexander Puchkov Mar 30 '17 at 18:15
  • 1
    Update: it didn't work on Windows 10, but luckily there's ubuntu inside Windows 10 anniversary update. Worked well there – Alexander Puchkov Mar 30 '17 at 19:09
  • 1
    @AlexanderPuchkov That is because you tried it in the Windows CMD prompt. It just happened to me too. If you had done it in the Git bash shell, it would have worked. – bart Nov 01 '18 at 15:00
  • Before proceeding make an backup branch from your current. This will literary recreate every commit with new initial commit -> I got 2 completely separated trees. Definitely this is NOT useful to remove just one simple empty commit! – Vladimir Vukanac Mar 10 '21 at 11:47
  • @VladimirVukanac that is expected if the first commit happened to be an empty commit. Note there is also a rebase option that allows you to specify an arbitrary bash script to be run prior to committing. That might be a better option, also because you can easily specify a starting point to the rebase action, hence leaving all earlier commits intact. – TamaMcGlinn Oct 16 '21 at 09:22