Reputation: 9457
I have run into a bit of a problem here: I had a problem-specific branch 28s
in Git, that I merged in the general develop
branch. Turns out I had done it too fast, so I used git-revert to undo the merge. Now, however, the time has come to merge 28s
into develop
, but git-merge command sees the original merge, and happily announces that all is well and branches have been already merged. What do I do now? Create a 'Revert "Revert "28s -> develop"" ' commit? Doesn't seem to be a good way to do it, but I can't imagine any other at the moment.
What the tree structure looks like:
Upvotes: 361
Views: 214137
Reputation: 31
What commands to run (assuming you are creating a PR):
# Starting from main branch
git checkout -b new-fix-branch
git revert <commit-hash-of-revert>
git reset --soft <commit-hash-of-commit-one-before-the-revert-of-revert>
# Gain peace of mind as you check everything is there.
git add -A
git commit -m "fix: brought back old changes"
# Congrats, syncing your branch will no longer remove the reverted changes.
Pros
Cons
Check-out to "main-branch" after a revert two commits ago:
main-branch ---o---o---(merge)---(revert)---o---(cool)*
/
feature-branch ---o---o
o = commits
(name) = named commits for clarity
* = head
Create new branch "new-fix-branch":
main-branch ---o---o---(merge)---(revert)---o---(cool)
/ |
feature-branch ---o---o |
new-fix-branch *
"git revert <hash-of-revert-commit>" giving us the old changes back:
main-branch ---o---o---(merge)---(revert)---o---(cool)
/ \
feature-branch ---o---o \
new-fix-branch (X-revert)*
X-revert = changes from original feature-branch, marked as revert in git
"git reset --soft <cool-commit-hash>" gives all the changes but un-committed & un-staged:
main-branch ---o---o---(merge)---(revert)---o---(cool)
/ |
feature-branch ---o---o |
new-fix-branch X*
X = changes from original feature-branch
stage & commit entire working tree, git now thinks changes are new:
main-branch ---o---o---(merge)---(revert)---o---(cool)
/ \
feature-branch ---o---o \
new-fix-branch (X)*
Fix & commit problem that caused issue (optional step), then merge:
main-branch ---o---o---(merge)---(revert)---o---(cool) (really-cool-merge)*
/ \ /
feature-branch ---o---o \ /
new-fix-branch (X)---(optional-fix)
No longer an issue where reverted changes disappear:
Sync branch with old reverted changes with main-branch:
main-branch ---o---(merge)---(revert)---o---(cool)---o---o---o
/ \ \
feature-branch ---o \ \
new-fix-branch (X)---(get-latest)*
Upvotes: 1
Reputation: 616
If needed you can create a new branch and cherry-pick the commits (separate the commit SH with space so it will be one command) from the reverted pull request, that way you'll be able to merge again with out losing files/changes.
Upvotes: 1
Reputation: 26930
You have to "revert the revert". Depending on you how did the original revert, it may not be as easy as it sounds. Look at the official document on this topic.
---o---o---o---M---x---x---W---x---Y
/
---A---B-------------------C---D
to allow:
---o---o---o---M---x---x-------x-------*
/ /
---A---B-------------------C---D
But does it all work? Sure it does. You can revert a merge, and from a purely technical angle, git did it very naturally and had no real troubles.
It just considered it a change from "state before merge" to "state after merge", and that was it.
Nothing complicated, nothing odd, nothing really dangerous. Git will do it without even thinking about it.So from a technical angle, there's nothing wrong with reverting a merge, but from a workflow angle it's something that you generally should try to avoid.
If at all possible, for example, if you find a problem that got merged into the main tree, rather than revert the merge, try really hard to:
- bisect the problem down into the branch you merged, and just fix it,
- or try to revert the individual commit that caused it.
Yes, it's more complex, and no, it's not always going to work (sometimes the answer is: "oops, I really shouldn't have merged it, because it wasn't ready yet, and I really need to undo all of the merge"). So then you really should revert the merge, but when you want to re-do the merge, you now need to do it by reverting the revert.
Upvotes: 240
Reputation: 2635
To revert a revert in GIT:
git revert <commit-hash-of-previous-revert>
Upvotes: 29
Reputation: 21
At this point you'll have a clean 'develop' branch to which you can merge your feature brach as you regularly do.
Upvotes: 2
Reputation: 13009
I would suggest you to follow below steps to revert a revert, say SHA1.
git checkout develop #go to develop branch
git pull #get the latest from remote/develop branch
git branch users/yourname/revertOfSHA1 #having HEAD referring to develop
git checkout users/yourname/revertOfSHA1 #checkout the newly created branch
git log --oneline --graph --decorate #find the SHA of the revert in the history, say SHA1
git revert SHA1
git push --set-upstream origin users/yourname/revertOfSHA1 #push the changes to remote
Now create PR for the branch users/yourname/revertOfSHA1
Upvotes: 3
Reputation: 3785
I just found this post when facing the same problem. I find above wayyy to scary to do reset hards etc. I'll end up deleting something I don't want to, and won't be able to get it back.
Instead I checked out the commit I wanted the branch to go back to e.g. git checkout 123466t7632723
. Then converted to a branch git checkout my-new-branch
. I then deleted the branch I didn't want any more. Of course this will only work if you are able to throw away the branch you messed up.
Upvotes: 2
Reputation: 17608
To revert the revert without screwing up your workflow too much:
Your feature branch should now be able to be merged as normal when you're ready for it. The only downside here is that you'll a have a few extra merge/revert commits in your history.
Upvotes: 60
Reputation: 3957
Let's assume you have such history
---o---o---o---M---W---x-------x-------*
/
---A---B
Where A, B failed commits and W - is revert of M
So before I start fixing found problems I do cherry-pick of W commit to my branch
git cherry-pick -x W
Then I revert W commit on my branch
git revert W
After I can continue fixing.
The final history could look like:
---o---o---o---M---W---x-------x-------*
/ /
---A---B---W---W`----------C---D
When I send a PR it will clearly shows that PR is undo revert and adds some new commits.
Upvotes: 87
Reputation: 471
Instead of using git-revert
you could have used this command in the devel
branch to throw away (undo) the wrong merge commit (instead of just reverting it).
git checkout devel
git reset --hard COMMIT_BEFORE_WRONG_MERGE
This will also adjust the contents of the working directory accordingly. Be careful:
git-reset
. All commits after the one you specify as
the git reset
argument will be gone!I recommend to study the git-reset
man-page carefully before trying this.
Now, after the reset you can re-apply your changes in devel
and then do
git checkout devel
git merge 28s
This will be a real merge from 28s
into devel
like the initial one (which is now
erased from git's history).
Upvotes: 5