Skip to content

Instantly share code, notes, and snippets.

@geelen
Created July 5, 2010 03:50
Show Gist options
  • Save geelen/463977 to your computer and use it in GitHub Desktop.
Save geelen/463977 to your computer and use it in GitHub Desktop.

Reverting multiple commits

Realised you can use git-reset in a funky way if you're trying to repair a repo that's got into a dodgy state. If you're working locally, you can use git reset --hard or git rebase -i or whatever to rewrite your history (if you're into that sort of thing) but when the commits have already been pushed things are slightly more complicated.

TL;DR

git reset --hard last_good_commit
git reset --soft ORIG_HEAD
git commit -m 'threw away changes back to last_good_commit'
git push
???
profit

The Problem

This morning I was faced with this sort of tree:

* 1c78d65 38 minutes ago Glen Maddern TRYING TO MERGE = EPIC CONFLICTS
|\
| * REAL CHANGES HERE
| * 5f57737 3 days ago Original Dev REVERT REVERT COMMIT A
| * f9d1722 3 days ago Original Dev REVERT REVERT COMMIT B
| * d857b0b 3 days ago On Call Dev REVERT COMMIT C          \
| * ffbd623 3 days ago On Call Dev REVERT COMMIT B           |- CHERRY PICKED
| * 9b8a510 3 days ago On Call Dev REVERT COMMIT A          /
| * REAL CHANGES HERE
* | d857b0b 3 days ago On Call Dev REVERT COMMIT C
* | ffbd623 3 days ago On Call Dev REVERT COMMIT B
* | 9b8a510 3 days ago On Call Dev REVERT COMMIT A
* | 0d811e7 4 days ago Glen Maddern MERGE MASTER -> PRODUCTION & DEPLOY
|\|
| * 5f0b1b7 4 days ago Glen Maddern LAST 'REAL' COMMIT THAT GOT DEPLOYED
| |

The problem was caused by reverting some commits to our production branch (which is fine, we're happy for our on-call dev to revert feature additions that break the site), cherry-picking those reverts into master, our main development branch, (which probably wasn't a good idea, in retrospect. Merging would have been better, and may have avoided the whole problem), the original dev then re-reverts and adds some extra fixes and our development branch is fine again.

Problem is, when merging the two branch, things explode. Git can't figure out that the two copies of REVERT COMMIT [ABC] are totally identical, especially when two of them got re-reverted. In fact, I'm impressed that it doesn't explode worse than it did (was hoping for a segfault).

The Solution

I guessed that the problem was entirely caused by the presence of duplicate reverted commits, caused by the cherry-picks. So I did this:

git checkout -b test 0d811e7
git merge --no-ff master

And everything merged fine. So, I just need to throw away the changes to production since 0d811e7 then merge in and bam. I could either re-revert the reversions, but that gave me the heebie-jeebies, so I did this instead:

git checkout production
git reset --hard 0d811e7
git reset --soft ORIG_HEAD

The point of this is to move to the last 'good' commit, then move the HEAD back to where it needs to be to preserve history, but without touching the repo. If you run a git status now, you'll now have a bunch of changes staged that undo all the commits between your HEAD and the last good commit. This is effectively a git revert --no-commit but for an arbitrary number of commits.

So, I then did

git commit -m 'threw away production hotfixes to deploy latest master'
git merge --no-ff master
git push
deploy_go!
main_screen_turn_on

And all was right with the world. I ended up with this tree:

* 1c78d65 19 minutes ago Glen Maddern MERGE HAPPINESS LIES HERE
|\
* | 400a87a 20 minutes ago Glen Maddern threw away production hotfixes to deploy latest master
| * REAL CHANGES HERE
| * 5f57737 3 days ago Original Dev REVERT REVERT COMMIT A
| * f9d1722 3 days ago Original Dev REVERT REVERT COMMIT B
| * d857b0b 3 days ago On Call Dev REVERT COMMIT C          \
| * ffbd623 3 days ago On Call Dev REVERT COMMIT B           |- CHERRY PICKED
| * 9b8a510 3 days ago On Call Dev REVERT COMMIT A          /
| * REAL CHANGES HERE
* | d857b0b 3 days ago On Call Dev REVERT COMMIT C
* | ffbd623 3 days ago On Call Dev REVERT COMMIT B
* | 9b8a510 3 days ago On Call Dev REVERT COMMIT A
* | 0d811e7 4 days ago Glen Maddern MERGE MASTER -> PRODUCTION & DEPLOY
|\|
| * 5f0b1b7 4 days ago Glen Maddern LAST 'REAL' COMMIT THAT GOT DEPLOYED
| |

-glen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment