54

I'm using the following sources to expunge some large files and directories from my repository:

http://dound.com/2009/04/git-forever-remove-files-or-folders-from-history/

Why is my git repository so big?

git filter-branch only seems to work on the current branch - is there a way to apply it to all branches at once?

Community
  • 1
  • 1
EoghanM
  • 20,021
  • 21
  • 80
  • 110

3 Answers3

80

The solution is simple:

git filter-branch [options] -- --all

Note the four dashes (two sets of double dashes with a space in between) in -- --all.

If you look at the docs for git-filter-branch, it says this:

git filter-branch [--env-filter <command>] [--tree-filter <command>]
    [--index-filter <command>] [--parent-filter <command>]
    [--msg-filter <command>] [--commit-filter <command>]
    [--tag-name-filter <command>] [--subdirectory-filter <directory>]
    [--prune-empty]
    [--original <namespace>] [-d <directory>] [-f | --force]
    [--] [<rev-list options>…]

Reading on, the beginning of the docs say: "Lets you rewrite git revision history by rewriting the branches mentioned in the <rev-list options>, applying custom filters on each revision."

So checking the docs for rev-list gives:

< rev-list options >… Arguments for git rev-list. All positive refs included by these options are rewritten. You may also specify options such as --all, but you must use -- to separate them from the git filter-branch options.

And the docs for git-rev-list say:

--all
Pretend as if all the refs in refs/ are listed on the command line as <commit>.
Ahmed Ashour
  • 4,209
  • 10
  • 29
  • 46
Ben Lee
  • 50,019
  • 12
  • 118
  • 142
  • 11
    just to clarify, normally `filter-branch` is listed with `HEAD` at the end, ` -- --all` replaces `HEAD` – EoghanM Sep 15 '11 at 12:59
  • How do I make it work in PowerShell (Windows)? It keeps erroring out and showing the help message for `filter-branch`. I have tried changing to double quotes as per Paul's answer, but I can't escape double quotes there (see my comments on the answer). – ADTC Aug 27 '14 at 10:34
  • 2
    I resolved the above by using pipes (in the PowerShell function). Basically: `git rev-list --all | git filter-branch [options]` (no rev-list at the end) instead of `git filter-branch [options] -- --all`. – ADTC Aug 28 '14 at 04:18
6

As @ben-lee's answer explains, --all is required for rewriting all branches. If you have tags in your repo, you'll want to clean all those, as well as the branches, in order get the benefits of reduction in size, and that will require an additional --tag-name-filter cat incantation.

Although the question specifies using git filter-branch, the questioner wants to 'expunge some large files and directories from my repository', so it's worth mentioning that the best tool for doing that is actually The BFG Repo Cleaner, a simpler, faster alternative to git filter-branch. For instance:

$ bfg --strip-blobs-bigger-than 10M

...removes all blobs bigger than 10MB (that aren't in your latest commit), and works on all branches & tags in your repo.

Full disclosure: I'm the author of the BFG Repo-Cleaner.

Community
  • 1
  • 1
Roberto Tyley
  • 21,540
  • 9
  • 67
  • 98
  • 1
    No problem @EoghanM - you might find this demo video interesting - it's a race between git filter-branch and The BFG (running on a Raspberry Pi...) http://www.youtube.com/watch?v=Ir4IHzPhJuI – Roberto Tyley Jan 22 '14 at 12:48
5

I followed all the instructions for doing this on my Windows box, but I kept getting an error, until I stopped using single quotes and used double quotes instead.

My motivation was that I accidentally checked in my vagrant environment. Here's the command to remove the vagrant folder from all branches:

git filter-branch --tree-filter "rm -rf vagrant" -f HEAD --all

Just replace vagrant with your directory name, and it'll remove this directory from all branches.

zb226
  • 7,475
  • 4
  • 37
  • 64
Paul Preibisch
  • 3,490
  • 2
  • 23
  • 27
  • Had this problem. Thank you! Also, if your command contains double quotes (like `' rm -rf "vagrant" '`), escape them using two double quotes (like `" rm -rf ""vagrant"" "`). – ADTC Aug 27 '14 at 10:10
  • Actually that doesn't work. Sure, that works for PowerShell but `git` simply errors out. – ADTC Aug 27 '14 at 10:16
  • There's a `git bash` on windows for a reason. Use it, sooner or later using git from cmd will hit you. – GiM Nov 17 '16 at 07:46