应用场景
当我们开发完某项功能,合并到 develop 分支后,其他人又提交了他们的代码。本来准备要上线了,这时由于某些原因,项目经理表示要撤回我们提交的代码,这个功能这次不上线了。这时候 git revert 就派上用场啦。
准备工作
我们来创建一个提交历史做实验。 首先创建一个 repo
1 | mkdir git-revert-merge-commit |
在 master 分支新建两个文件 file1, file2,提交。
1 | echo 'file1' > file1 |
现在我们要做一个新的 feature,我们从 master 分支切出 feature 分支来。然后新建两个文件 file3, file4,并提交。
1 | git branch feature |
在我们开发 feature 的过程中,master 上通常还有别人的提交。这时候我们回到 master 分支上,创建文件 file5, file6 ,提交。
1 | git checkout master |
OK,这个时候,我们把 feature 合并到 master 上去。先给他打个标签。
1 | git checkout feature |
好了,其他人也没闲着,又在 master 分支上新建了 file7
1 | echo 'file7' > file7 |
好了,咱们来看一眼 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 。