Thank IT

以应用为导向的个人博客。日拱一卒,功不唐捐,以此共勉。

0%

用 git revert 撤回 merge 了的 commit

应用场景

当我们开发完某项功能,合并到 develop 分支后,其他人又提交了他们的代码。本来准备要上线了,这时由于某些原因,项目经理表示要撤回我们提交的代码,这个功能这次不上线了。这时候 git revert 就派上用场啦。

准备工作

我们来创建一个提交历史做实验。 首先创建一个 repo

1
2
3
mkdir git-revert-merge-commit
cd git-revert-merge-commit
git init

在 master 分支新建两个文件 file1, file2,提交。

1
2
3
4
echo 'file1' > file1
git add . && git commit -m 'commit file 1 on master'
echo 'file2' > file2
git add . && git commit -m 'commit file 2 on master'

现在我们要做一个新的 feature,我们从 master 分支切出 feature 分支来。然后新建两个文件 file3, file4,并提交。

1
2
3
4
5
6
git branch feature
git checkout feature # 或者使用 git checkout -b feature 一键完成上述两步
echo 'file3' > file3
git add . && git commit -m 'file3 on feature'
echo 'file4' > file4
git add . && git commit -m 'file4 on feature'

在我们开发 feature 的过程中,master 上通常还有别人的提交。这时候我们回到 master 分支上,创建文件 file5, file6 ,提交。

1
2
3
4
5
git checkout master
echo 'file5' > file5
git add . && git commit -m 'file 5 on master'
echo 'file6' > file6
git add . && git commit -m 'file 6 on master'

OK,这个时候,我们把 feature 合并到 master 上去。先给他打个标签。

1
2
3
4
5
git checkout feature
git tag thumbup-feature
git checkout master
git pull origin master # 拉取远程 master 合并到本地 master 没有远程就跳过。
git merge thumbup-feature --no-ff # --no-ff 是为了避免 fast-forward

好了,其他人也没闲着,又在 master 分支上新建了 file7

1
2
echo 'file7' > file7
git add . && git commit -m 'file 7 on master'

好了,咱们来看一眼 source tree 中的提交记录。

实验

这时候,项目经理要求撤回你的 feature ,就是撤回 file3, file 4 on feature。 我们 merge 的 commit id 是 4ff73d0

1
git revert 4ff73d0

会报错: 看下官方文档的说法:

-m parent-number —mainline parent-number Usually you cannot revert a merge because you do not know which side of the merge should be considered the mainline. This option specifies the parent number (starting from 1) of the mainline and allows revert to reverse the change relative to the specified parent. Reverting a merge commit declares that you will never want the tree changes brought in by the merge. As a result, later merges will only bring in tree changes introduced by commits that are not ancestors of the previously reverted merge. This may or may not be what you want.

我们看到 merge 的 commit 有两个 parents

1
git revert 4ff73d0 -m 1

将以 file 6 on master 那次提交作为 base, 那么撤回的是 file 3, file 4。 结果如下: 这时候我们恢复到上面一次提交,撤销这次的 revert 操作。

1
git reset --hard df521a0

然后尝试

1
git revert 4ff73d0 -m 2

将以 file 4 on feature 那次提交作为 base, 撤回 file 5, file 6. 如果我们继续

1
git revert 4ff73d0 -m 1

那么跟之前一样,将以 file 6 on master 那次提交作为 base, 撤回 file 3, file 4。 至此 file3,file4,file5,file6 全部撤销。

总结

git revert -m {n} 可以用来撤销 merge 了的 commit 。

参考链接

当你决定去 revert 一个merge commit