Git的版本还原的几种场景
郝伟 2022/03/13

简介

之前写过两篇关于GIt还原文章,包括:【Git实战记录】撤销已经提交至远程的一次变更【Git】checkout,reset和 revert 命令比较。但是文章并没有把具体的还原的应用场景进行区分,所以本文就还原问题进行进一步描述。

场景1:本地修改还没提交 (uncommit)

本地代码在进行了修改以后,尚未使用 commit 命令进行提交,所以实际上新修改的数据还没有添加到版本控制中来,所以此时,只需要放弃当前修改的版本内容即可。需要注意的是,虽然逻辑上是放弃修改,但是实际上的实现过程是反过来的,即用最新版本的内容替换现有的修改的内容。

举例来说,现在仓库R已提交版本信息如下:R:V0V1V2R: V_0 \rightarrow V_1 \rightarrow V_2

当前为最新版,即V2V_2。如果本地代码进行了修改,假设为V3V_3,由于V3V_3还没有提交到仓库中,所以撤消这个修改将本地内容还原为V2V_2的实际操作是:将V2V_2提取后替换V3V_3。常规的版本控制软件都有这个功能,一般名称都叫“撤销”,而在后台调用的是 `checkout1 命令。只需要在已经修改的文件列表中,执行这个操作即可。

注意:在编辑器中未保存的内容是不会撤销的,所以在撤销前,务必保存所有的文件。

场景2:本地代码已提交 (committed)

撤回提交 (undo commit)

撤回当前提交相当于把已经提交的内容再撤回到未提交状态,用户可以再次编辑后再次提交。不少编辑器提供了这样的功能,可以直接在对已经修改的内容使用这个操作,这样已经提交的内容就变成了未提交状态,相当于撤销到提交前的状态。这时就可以直接将错误的内容起进行修改,然后重新提交。

举例来说,

注意

  1. 在命令层面并不存在 undo commit 命令,而是使用的是 git reset –soft HEAD~1 实现。
  2. 虽然可以撤销多次提交的内容,但每次只能撤销最后一次提交。如有2个版本要撤销时,要操作2次,其中第2次的变更会叠加到第1次上。

撤销某个提交

如果某个版本不需要了,我们可以使用使用 revert 命令将这个版本的变更全部撤销。

原理: git revert是用于“反做”某一个版本,以达到撤销该版本的修改的目的。比如,我们commit了几个版本 V0,V1,V2,V3V_0, V_1, V_2, V_3,突然发现 V2V_2 是有人错误的修改,所以需要撤销。此版本后面又有了一些提交,要求保留这些提交。这时我们就可以用 git revert 命令只撤销V2V_2的修改,并在保留后续提交的基础上生成新的版本 V4V_4,即新版本只会保留 V0,V1,V2V_0, V_1, V_2的内容,好像 V2V_2不存在一样。

注意:撤销中间的某个版本可能会造成在整合时,造成文件冲突。如 V1V_1中和V3V_3中同时对某个文件的同一行进行了修改,则会产生冲突提示。

删除提交

如果某个提交完全无用,或者可能是别人恶意提交的,那么可以直接删除此提交。
可以使用 git reset HARD 将修改回滚到某个版本VnV_n,而VnV_n后面的版本将会被直接删除。

版本切换

git swith 可以在版本和分支间切换,
当执行了 git swith… 命令后,会导致本地脱机,可以使用 git switch master 切换回来。

参考:
[1] How to undo last commit in Git?
[2] 在Pycharm中使用Git进行版本控制时,undo commit和revert的区别

场景3:代码已经提交到远程

具体参考此文 【Git实战记录】撤销已经提交至远程的一次变更

总结

三个命令的作用: