My experience to GIT is low to none, so what I'm asking may sound a bit odd. We have an Azure Devops repo, with commits on daily basis.
A commit with some changes happened in our Azure Devops repository on the 3rd of September. This was committed, but never pushed. The developer was absent since, and in the past 2 months a lot of commits happened. Then, on the 21st of October, the commit from the 3rd of September was merged with all the commits in between and finally pushed.
Is there a way to revert the merged commit (that happened on the 21st of Oct) AND the commit itself (that happened on the 3rd of Sept) without losing all the commits in between?
This is happening in Azure Devops, and the commits and pushes were going mainly through Visual Studio 2019.
CodePudding user response:
As @RomainValeri pointed out in the comments, the git revert
command is what you're looking for here.
First, let's visualize the situation:
o---o---o---o---o---X---M
\ /
A----------------
Here, commit A
is the one from September 3rd and M
is the merge commit from October 21st.
You mentioned that you want to revert just the changes introduced by A
from the branch that contains M
. You can do so by reverting the merge commit M
with:
git revert -m 1 M
where M
is a reference pointing to the merge commit.
Now, since a merge commit has 2 or more parents, you also need to tell Git which of the parents it should use as a baseline to determine what changes it should revert. That's what the -m
(--mainline
) option is for. In this case, we want the target branch (i.e. the branch where A
was merged into) to be the baseline, so we say -m 1
, a.k.a the first parent.
This will apply the reverse of the differences between the first parent of M
(in this example, X
) and A
in a new commit W
:
o---o---o---o---o---X---M---W
\ /
A----------------
It's common to refer to the reverse of a merge commit as W
, since it looks like an upside down M
.
Keep in mind that reverting a merge commit undoes the changes, but it doesn't undo the history. In other words, Git will still consider the branch that was merged with M
to be merged even after W
. If you tried to merge it again, Git would tell you that everything is up-to-date.
So, if you want to merge that same branch again in the future, you'll have to revert the revert first. Have a look at this how-to from Git's documentation for details on how to do that.