LV015-版本回退
【说明】本节笔记的相关操作在 Windows 下进行,因为 VS Code 有个 Git 的插件,可以很直观的演示一些东西。由于 Git 安装后自带一个 Git-Bash 终端,所以就不用 Win 下的命令行啦,就用的这个终端,因为它里边的命令与 Linux 很类似,而 windows 中的命令行有些命令与 linux 并不相同,为了统一,还是用用 Git 自带的终端啦。另外 VS Code 是可以选择使用的终端的,我直接将 VS Code 使用的终端改成了 git-bash,这样更方便一些。
一、文件准备
我们这里重新准备一个版本库用于这一节笔记的使用:
git init
touch readme.md
git add .
git commit -m "feat:创建本地版本库并进行第一次提交(readme文件为空)"
二、撤销操作
1. 修改上次提交
1.1 情况说明
我们上边创建了一个空的 readme.md 文件,并且提交了,但是,现在我们希望创建一个 test.c 文件,并且将 test.c 这个文件的功能写入到 readme 文件中。
一般来讲,我们可以重新提交一次,但是这就意味着版本库中有两个提交记录,但是其实根本没必要有两个提交记录啊,readme 文件本来就是记录一些说明信息的,那么现在我们 既想将新文件提交上去,又不想产生两次提交记录,那么要怎么样解决呢?
1.2 命令说明
此时,为了解决上边的问题,我们可以运行带有 –amend 选项的提交命令来重新提交,这样可以避免让仓库历史纪录变得复杂,一般格式如下:
git commit --amend -m "新的描述" # 如果不加-m 参数,系统会让进行输入的
git commit --amend --no-edit # 不修改描述,只是添加新文件这个命令会将暂存区中的文件提交。 如果自上次提交以来我们还未做任何修改(例如,在上次提交后马上执行了此命令), 那么快照会保持不变,而我们所修改的只是提交信息。
当我们在修补最后的提交时,与其说是修复旧提交,倒不如说是完全用一个 新的提交 替换旧的提交。从效果上来说,就像是旧有的提交从未存在过一样,它并不会出现在仓库的历史中。
修补提交最明显的价值是可以稍微改进我们最后的提交,而不会让“啊,忘了添加一个文件”或者 “小修补,修正笔误”这种提交信息弄乱我们的仓库历史。
1.3 使用实例
1.3.1 查看文件状态
我们需要创建一个 test.c 文件,然后再修改 readme 文件,完成后,文件状态如下:

1.3.2 重新提交
我们重新提交这一次的修改:
git add .
git commit --amend # 重新提交然后,Git 就会打开默认的编辑器,可以看到之前的提交信息,我们编辑后保存会覆盖原来的提交信息。

提交后如下图所示:

1.3.3 提交记录
我们使用自定义的 git 命令查看一下提交记录:

会发现,整个仓库就只有这一条提交记录。也就是我们第二次提交的结果代替了第一次提交,就相当于第一次提交没有存在一样。
2. 撤销对文件的修改
这部分说的文件修改还暂未提交到暂存库,也就是修改文件之后,git add 之前的状态。
2.1 情况说明
我们现在对 test.c 做一系列的修改,这个时候我们并未但是改完之后,这些修改我不想要了,我并不想保留对这个文件的修改,这个时候怎么办,一行一行吧修改的地方删掉吗?是个办法,对于我们测试文件来说,比较简单,倒无所谓,可是当我们在大型项目中开发,修改了大量的文件的时候,也不想保留修改这该怎么办?也一个一个改嘛,这显然是不现实的。
那么我们该如何方便地撤消修改——将它还原成上次提交时的样子(或者刚克隆完的样子,或者刚把它放入工作目录时的样子)? 幸运的是,git status 也告诉了我们应该如何做。
2.2 git status 的提示
我们来修改一下 test.c 文件,然后看一下 git status 命令有什么提示:

可以看到,有这么一句话:
(use "git restore <file>..." to discard changes in working directory)这个命令其实就可以用于撤销我们对于文件的修改。
2.3 撤销命令
其实可以达到撤销未暂存的文件的修改的命令不仅仅上边这一个,还有一个 checkout,具体为什么 git status 命令没有给出提示,还不清楚,不过不重要,我们知道就可以了:
git checkout -- <file>...
git restore <file>...<file>... 可以是多个文件,当然要是我们想直接撤销所有文件的修改,那么可以直接用下边的两个命令:
git checkout -- .
git restore .需要特别注意,这两个命令是很 危险的命令。 我们对那个文件在本地的 任何修改都会消失——Git 会用最近提交的版本覆盖掉它。 除非我们确实清楚不想要对那个文件的本地修改了,否则最好不要使用这个命令。
2.4 使用实例
我们用 git checkout 来试一下吧:
git checkout -- test.c然后我们会看到如下信息:

如果我们仍然想保留对那个文件做出的修改,但是现在仍然需要撤消,我们将会在 Git 分支 介绍保存进度与分支,这通常是更好的做法。在 Git 中任何 已提交 的东西几乎总是可以恢复的。 甚至那些被删除的分支中的提交或使用 --amend 选项覆盖的提交也可以恢复 (阅读 数据恢复 了解数据恢复)。 然而,任何我们未提交的东西丢失后很可能再也找不到了。
3. 取消暂存的文件
这一部分是针对我们修改了文件,并且已经通过 git add 添加到暂存区的文件。
3.1 情况说明
现在有这样的情况,我们已经修改了两个文件并且想要将它们作为两次独立的修改提交, 但是却意外地输入 git add * 或者 git add . 暂存了它们两个。但是这两个文件我想作为两次提交,有两个提交记录便于追溯,那么如何只取消暂存两个中的一个呢?
3.2 git status 的提示
我们来修改一下 test.c 和 readme 文件,然后看一下 git status 命令有什么提示:

修改完毕后,我们将修改提交到暂存区,然后查看一下文件状态:
git add .
git status
可以看到,有这么一句话:
(use "git restore --staged <file>..." to unstage)这个命令其实就可以用于撤销我们对于文件的修改。
3.3 撤销命令
其实撤销提交到暂存区的修改为命令一共有两个,但是 git 提示只给出了一个:
git restore --staged <file>...
git reset HEAD <file>...< file >...可以是多个文件,当然要是我们想直接撤销所有文件的修改,那么可以直接用下边的两个命令:
git restore --staged .
git reset HEAD .这两个命令没有想象中那么危险,我们取消暂存区的修改后,这些修改还保留在工作区,只是回到了我们刚修改完文件的状态。
3.4 使用实例
我们用 git restore 来试一下吧:
git restore --staged test.c然后我们会看到如下信息:

可以看到 test.c 文件已经回到了未提交到暂存库的状态了。
3.5 提交更新
我们将上面的更改提交到版本库中,方便后边继续使用此仓库做测试。
git commit -m "feat:取消暂存文件测试(修改readme文件)"
git add .
git commit -m "feat:取消暂存文件测试(修改test.c文件)"可以看到当前的提交记录如下:

三、版本回退
1. 情况说明
现在我们产生了 v1、v2、v3 三次提交,如下图所示,主要以 test.c 修改来做测试:

v1、v2 和 v3 的提交,分别对应一行内容:

现在,我们不想要 v2 和 v3 的提交了,我现在需要回到版本 v1,这该怎么办?
2. 跳到指定版本
Git 给我们提供了一个命令,用于跳到指定的提交节点去,也可以叫版本回滚吧:
git reset --hard <版本号> # 回到指定版本, 版本号即为每次提交的 hash 值3. 查看提交记录 hash 值
要想通过上边的命令来跳转到指定的版本,我们就需要知道这个指定的版本提交记录的 hash 值,我们有两个命令:
git reflog # 查看所有提交记录(包括因为回滚丢失的记录)
git log # 查看所有提交记录其实这里查看所有提交记录的时候,也可以使用 git log 指令来查看,那么该指令与 git reflog 区别在哪里呢?
git reflog命令可以查看 所有分支的所有操作 记录信息,包括 已经被删除的 commit 记录和 reset 的操作。git log命令可以显示 当前分支所有提交过 的版本信息,不包括 已经被删除的 commit 记录和 reset 的操作。(注意: 只是当前分支操作的信息)。
所以,当我们回滚版本回滚错了的时候,想要恢复回滚之前的版本的话, git reflog 就为该操作的实现提供了可能,后边会提到的。
4. 使用实例
4.1 查看提交记录
这一步主要是为了获取跳转的版本的 hash 值:
git mylog # 用自定义的方便看
我们要想跳转到 v1 版本的话,它对应的 hash 值为 b065bb7。
4.2 跳转指定版本
我们现在执行下边的命令,跳转到 v1 提交的时候:
git reset --hard b065bb7执行完毕后,我们会得到以下提示:

然后我们再看一下提交记录和文件:

可以看到文件回到了 v1 版本的时候,并且提交记录也只剩下 v1 及以前了。
5. git reflog 的应用
5.1 情况说明
上边我们已经跳转到 v1 的版本了,可是这个时候,突然发现 v2 版本也是很重要的,我现在想到 v2 版本去,可是那次提交貌似被我们丢掉了哎?怎么办?这个时候 git reflog 就派上用场了。
5.2 查看所有提交记录
我们执行下边的命令,看一下会有什么输出:
git reflog然后我们会得到以下输出信息:

这两个不就是我们的 v2 和 v3 的提交嘛,这样我就就可以获取这两次提交的 hash 值了,例如 v2 提交记录的 hash 为 68b6e33。
5.3 跳转到指定版本
我们执行以下命令跳转到 v2 版本的提交:
git reset --hard 68b6e33然后我们看一下文件和提交记录:

可以看到目前已经位于 v2 提交记录的版本啦。