Given a change that has been committed using commit
, and then reverted using revert
, what is the best way to then undo that revert?
Ideally, this should be done with a new commit, so as to not re-write history.
Given a change that has been committed using commit
, and then reverted using revert
, what is the best way to then undo that revert?
Ideally, this should be done with a new commit, so as to not re-write history.
git cherry-pick <original commit sha>
Will make a copy of the original commit, essentially re-applying the commit
Reverting the revert will do the same thing, with a messier commit message:git revert <commit sha of the revert>
Either of these ways will allow you to git push
without overwriting history, because it creates a new commit after the revert.
When typing the commit sha, you typically only need the first 5 or 6 characters:git cherry-pick 6bfabc
A revert commit is just like any other commit in git. Meaning, you can revert it, as in:
git revert 648d7d808bc1bca6dbf72d93bf3da7c65a9bd746
That obviously only makes sense once the changes were pushed, and especially when you can't force push onto the destination branch (which is a good idea for your master branch). If the change has not been pushed, just do cherry-pick, revert or simply remove the revert commit as per other posts.
In our team, we have a rule to use a revert on Revert commits that were committed in the main branch, primarily to keep the history clean, so that you can see which commit reverts what:
7963f4b2a9d Revert "Revert "OD-9033 parallel reporting configuration"
"This reverts commit a0e5e86d3b66cf206ae98a9c989f649eeba7965f.
...
a0e5e86d3b6 Revert "OD-9055 paralel reporting configuration"
This reverts commit 648d7d808bc1bca6dbf72d93bf3da7c65a9bd746.
...
Merge pull request parallel_reporting_dbs to master* commit
'648d7d808bc1bca6dbf72d93bf3da7c65a9bd746'
This way, you can trace the history and figure out the whole story, and even those without the knowledge of the legacy could work it out for themselves. Whereas, if you cherry-pick or rebase stuff, this valuable information is lost (unless you include it in the comment).
Obviously, if a commit reverted and re-reverted more than once that becomes quite messy.
Here's how I did it:
If the branch my_branchname
was included in a merge that got reverted. And I wanted to unrevert my_branchname
:
I first do a git checkout -b my_new_branchname
from my_branchname
.
Then I do a git reset --soft $COMMIT_HASH
where $COMMIT_HASH
is the commit hash of the commit right before the first commit of my_branchname
(see git log
)
Then I make a new commit git commit -m "Add back reverted changes"
Then I push up the new branch git push origin new_branchname
Then I made a pull request for the new branch.
If you don't like the idea of "reverting a revert" (especially when that means losing history information for many commits), you can always head to the git documentation about "Reverting a faulty merge".
Given the following starting situation
P---o---o---M---x---x---W---x
\ /
A---B---C----------------D---E <-- fixed-up topic branch
(W is your initial revert of the merge M; D and E are fixes to your initially broken feature branch/commit)
You can now simply replay commits A to E, so that none of them "belongs" to the reverted merge:
$ git checkout E
$ git rebase --no-ff P
The new copy of your branch can now be merged to master
again:
A'---B'---C'------------D'---E' <-- recreated topic branch
/
P---o---o---M---x---x---W---x
\ /
A---B---C----------------D---E
I had an issue somebody made a revert to master to my branch, but I was needed to be able to merge it again but the problem is that the revert included all my commit. Lets look at that case we created our feature branch from M1 we merge our feature branch in M3 and revert on it in RM3
M1 -> M2 -> M3 -> M4- > RM3 -> M5
\. /
F1->F2 -
How to make the F2 able to merge to M5?
git checkout master
git checkout -b brach-before-revert
git reset --hard M4
git checkout master
git checkout -b new-feature-branch
git reset --hard M1
git merge --squash brach-before-revert
I saw responses include the command git reset --hard HEAD
without any caution. You should be careful with that command because of the option --hard
. It resets your index and your remote repo but mostly, it also resets your local repo and all commits that were not pushed to the remote yet will be lost, both from your local repo and index. Never use that flag --hard
unless you are sure you also want to reset all your local work from the current commit till the hash you chose.
If anyway you did it by mistake, run git reflog
to retrieve your ~hash then git reset --hard ~hash
to recover your files.