gitgit-filter-branchgit-rewrite-historygit-rm

How do you fix a bad merge, and replay your good commits onto a fixed merge?


I accidentally committed an unwanted file (filename.orig while resolving a merge) to my repository several commits ago, without me noticing it until now. I want to completely delete the file from the repository history.

Is it possible to rewrite the change history such that filename.orig was never added to the repository in the first place?


Solution

  • Please don't use this recipe if your situation is not the one described in the question. This recipe is for fixing a bad merge, and replaying your good commits onto a fixed merge.

    Although filter-branch will do what you want, it is quite a complex command and I would probably choose to do this with git rebase. It's probably a personal preference. filter-branch can do it in a single, slightly more complex command, whereas the rebase solution is performing the equivalent logical operations one step at a time.

    Try the following recipe:

    # create and check out a temporary branch at the location of the bad merge
    git checkout -b tmpfix <sha1-of-merge>
    
    # remove the incorrectly added file
    git rm somefile.orig
    
    # commit the amended merge
    git commit --amend
    
    # go back to the master branch
    git checkout master
    
    # replant the master branch onto the corrected merge
    git rebase tmpfix
    
    # delete the temporary branch
    git branch -d tmpfix
    

    (Note that you don't actually need a temporary branch, you can do this with a 'detached HEAD', but you need to take a note of the commit id generated by the git commit --amend step to supply to the git rebase command rather than using the temporary branch name.)