Recent versions of git filter-branch command introduced the --state-branch option. BTW I can't find any info about how this can be actually used. We have this repository on github: https://github.com/concrete5/concrete5 When someone pushes to that repo, we clone it and execute `git filter-branch --subdirectory-filter concrete` to extract the concrete directory, and we push the result to https://github.com/concrete5/concrete5-core (including all the branches and tags) The script at the moment is this one: https://github.com/concrete5/core_splitter/blob/70879e676b95160f7fc5d0ffc22b8f7420b0580b/bin/splitcore I tried to use the --state-branch option on a local mirror, so that we could do an incremental filtering. Here's the script: # Executed just one time git clone --no-checkout --mirror \ https://github.com/concrete5/concrete5.git work cd work git filter-branch \ --subdirectory-filter concrete \ --tag-name-filter cat \ --prune-empty \ --state-branch FILTERBRANCH_STATE \ -- --all # Executed every time the repo is updated git remote update --prune git filter-branch \ --subdirectory-filter concrete \ --tag-name-filter cat \ --prune-empty \ --state-branch FILTERBRANCH_STATE \ -- --all The first filter-branch call required 7168 steps, so did the second call... I also tried without the --prune option of remote update (I had to add --force to the second filter-branch), but nothing changed.