本文首先对常用的 Revert,Reset 回退代码命令进行了讲解。希望可以讲明白它们的弊端。最后介绍如何使用 Rebase 优雅回退代码。
使用命令 git revert commit_id
能产生一个 与 commit_id
完全相反的提交,即在 log 中会看到一条新的提交 new_commit_id
, revert
提交就是删除 commit_id 的提交。
# 查看提交记录
$ git log -p
# 回退某个提交
$ git revert commit_id
# 取消执行回退
$ git revert --abort
# revert merge commit
# 一般来说,如果在 master 上 merge a_branch,那么 parent 1 就是 master,parent 2就是 a_branch。
# git revert merge_commit_id -m parent
$ git revert b7b7b87d5d05a22ad1e7779484bcf82e31041a72 -m 1
mainline
。
这个 mainline 是主线,也是我们要保留代码的主分支,从 feature 分支往 develop 分支合并,或由 develop 分支合并到 master 的提交还好确定,但 feature 分支互相合并时,难以区分主线。reset
也能使代码回到某次提交,但跟 revert
不同的是, reset
是将提交的 HEAD
指针指到某次提交,之后的提交记录会消失,就像从没有过这么一次提交。
# 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变
$ git reset [file]
# 重置暂存区与工作区,与上一次commit保持一致
$ git reset --hard
# 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变
$ git reset [commit]
# 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致
$ git reset --hard [commit]
# 重置当前HEAD为指定commit,但保持暂存区和工作区不变
$ git reset --keep [commit]
rebase
把多个提交合并成一个提交,再使用revert
产生一次反提交,这种方法的思路非常清晰,把revert
和rebase
两个命令搭配得很好,相当于使用revert
回退的升级版,其实现更优雅,便捷,强大。
rebase
是“变基”的意思,这里的“基”,指[多次] commit
形成的 git workflow
,使用 rebase
,我们可以改变这些历史提交,修改 commit
信息,将多个 commit
进行组合。后续写一篇文章详细介绍 rebase
。
# 执行变基
$ git rebase -i commit_n
# 终止变更
$ git rebase --abort
1). 切出一个新分支 rebase-rollback
首先,切出一个新分支 rebase-rollback
,使用 git log 查询一下要回退到的 commit 版本 commit_n。如下图回退到蓝框中的版本。
2). 执行命令 git rebase -i commit_n
-i
指定交互模式后,会打开 git rebase
编辑界面。
$ git rebase -i fa1b56d920e636914b6ef27988358ff122279261
编辑界面看到形如下述的 commit:
pick 6fa5869 commit1
pick 0b84ee7 commit2
pick 986c6c8 commit3
pick 91a0dcc commit4
3). 合并 commit2 ~ commitN 到最旧的 commit1 上 在合并 commit 时,我们可以选择 pick(p) 最旧的 commit1,然后在后续的 commit_xxx 前添加 squash(s) 命令,将这些 commits 都合并到最旧的 commit1 上。
编辑界面修改后形如下述的 commit:
pick 6fa5869 commit1
squash 0b84ee7 commit2
squash 986c6c8 commit3
squash 91a0dcc commit4
4). 保存 rebase 结果后,再编辑 commit 信息,使这次 rebase 失效 git 会将之前的这些 commit 都删除,并将其更改合并为一个新的 commit5。如果出错了,也可以使用 git rebase –abort/–continue/–edit-todo 对之前的编辑进行撤销、继续编辑
冲突处理出现冲突时,需处理冲突后,再执行 –continue。处理冲突时一般选择
# fix conflicts and then run "git rebase --continue"
$ git rebase --continue
# 执行成功提示语
Successfully rebased and updated refs/heads/rebase-rollback.
5). 检查 rebase 执行成功
主干提交记录 执行下述命令,查看主干的提交记录:
master
提交记录 commits
形如:
rebase-rollback 分支提交记录 执行下述命令,查看 rebase-rollback 分支的提交记录:
master
提交记录 commits
形如:
6). 合并 master 到 rebase-rollback
由于 rebase-rollback
分支落后与 master 分支,因此需要执行 git merge master
将主分支向 rebase-rollback
分支合并,合并后 git 会发现 commit1 到 commit4 提交的内容和 rebase-rollback
分支上 commit5 的修改内容是完全相同的,会自动进行合并,内容不变,但多了一个 commit5。
7). 在 rebase-rollback 执行 revert 反提交
在 rebase-rollback
分支上对 commit5 进行一次 revert 反提交,就实现了把 commit1 到 commit4 的提交全部回退。即撤回步骤6中的合并。
$ git revert 5c6123b94705ea605d404fc03aad90b23ab156bd
8). 合并 rebase-rollback 到 master
# 切回到 master
$ git checkout master
# 合并 rebase-rollback
$ git merge rebase-rollback