Note: this answer is about shortening history of a whole project, rather than removing single file from older history what the question was about!
The simplest way to shorten history of a whole project by using git filter-branch would be to use grafts mechanism (see repository layout documentation) to shorten history:
$ echo "$commit_id" >> .git/info/grafts
where $commit_id
is a commit that you want to be a root (first commit) of a new repository. Check out using "git log" or graphical history viewer such as gitk that the history looks like you want, and run "git filter-branch --all"; the use of grafts is described in git-filter-branch documentation.
Or you can use shallow clone by using --depth <depth>
option of git clone.
You can make use of grafts to remove part history of a single file (what was originally requested) using steps describe below. This solution consists of more steps than solution proposed by Dan Moulding, but each of steps is simpler, and you can check intermediate steps using "git log" or graphical history viewer.
First, select point where you want to have file removed, and mark those commits by creating branches at those points. For example if you want to have file appear for first time in commit f020285b
and have it removed in all it ancestors, mark it ancestor (assuming this is ordinary, non-merge commit) using
$ git branch cleanup f020285b^
Second, remove the file from the history beginning with cleanup
(i.e. f020285b^
) using git-filter-branch, as shown in "Examples" section of git-filter-branch manpage:
$ git filter-branch --index-filter 'git rm --cached --ignore-unmatch big_manual.txt' cleanup
If you want to remove also all commits which had changed only to removed file you can additionally use --prune-empty
option to git-filter-branch.
Next, join rewritten part of history with the rest of history using grafts mechanism:
$ echo $(git-rev-parse f020285b) $(git rev-parse cleanup) >> .git/info/grafts
Then you can examine histry to check if it is joined correctly.
Last, make grafts permanent (this would make all grafts permanent, but lets assume here that you don't use grafts otherwise) using git-filter-branch,
$ git filter-branch cleanup..HEAD
and remove grafts (as they are not needed any more), and the cleanup
branch
$ rm .git/info/grafts
$ git branch -d cleanup
Final note: if you remove part of history of some file, you better make sure that project without this file makes sense (and for example compiles correctly).