Git入门(七):版本回退

跟着之前的教程,我相信你已经熟练掌握了如何修改文件并提交这些修改到Git版本库中。接下来,我们再次练习一下这个过程。首先,我们要修改readme.txt文件,使其内容如下:

Git is a distributed version control system.  
Git is free software distributed under the GPL.

完成修改后,我们将这些更改提交到Git版本库中:

$ git add readme.txt  
$ git commit -m "append GPL"  
[master 1094adb] append GPL  
 1 file changed, 1 insertion(+), 1 deletion(-)

每当你对文件进行了一系列的修改,并认为这些修改达到了一个可以保存的状态时,你可以使用git add命令将这些修改添加到暂存区,然后使用git commit命令将这些修改提交到Git版本库中。这就像是在游戏中每通过一个关卡就保存一次进度,或者在打Boss前手动存档,以便在失败时能够从最近的保存点重新开始。

现在,让我们回顾一下readme.txt文件的提交历史:

版本1:wrote a readme file

Git is a version control system.  
Git is free software.

版本2:add distributed

Git is a distributed version control system.  
Git is free software.

版本3:append GPL

Git is a distributed version control system.  
Git is free software distributed under the GPL.

当然,对于一个包含数千行的文件,我们很难记住每次提交都做了哪些更改。这正是版本控制系统发挥作用的地方。在Git中,我们可以使用git log命令来查看提交历史记录:

$ git log  
commit 1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master)  
Author: LiHua <example@mail.com>  
Date:   Fri April 4 21:06:15 2024 +0800  
  
    append GPL  
  
commit e475afc93c209a690c39c13a46716e8fa000c366  
Author: LiHua <example@mail.com>  
Date:   Fri April 4 21:03:36 2024 +0800  
  
    add distributed  
  
commit eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0  
Author: LiHua  <example@mail.com>  
Date:   Fri April 4 20:59:18 2024 +0800  
  
    wrote a readme file

通过git log命令,我们可以看到从最近到最远的提交日志。在这个例子中,我们可以看到三次提交,最近的一次是“append GPL”,上一次是“add distributed”,而最早的一次是“wrote a readme file”。

如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数:

$ git log --pretty=oneline
1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master) append GPL
e475afc93c209a690c39c13a46716e8fa000c366 add distributed
eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 wrote a readme file

友情提示一下,你所看到的那串如“1094adb…”的数字是commit id(版本号)。与SVN不同,Git的commit id并不是像1、2、3这样递增的数字。它是一个通过SHA1算法计算得出的非常大的数字,以十六进制的形式表示。你看到的commit id与我所看到的肯定是不同的,每个人的commit id都是唯一的。

为什么commit id需要使用这么一大串数字来表示呢?这主要是因为Git是一个分布式的版本控制系统。在后续的学习中,我们将研究多人在同一个版本库中协同工作的情况。如果大家都使用1、2、3这样的数字作为版本号,那么很容易就会发生版本冲突。而使用SHA1算法生成的这一大串数字作为commit id,可以确保在全球范围内都是唯一的,从而避免了版本冲突的问题。这样的设计使得Git成为一个强大且灵活的版本控制系统。

好的,现在我们将启动时光穿梭机,回退到readme.txt的上一个版本,也就是“add distributed”的那个版本。在Git中,HEAD表示当前版本,即最新的提交。因此,上一个版本可以通过HEAD^来表示,上上一个版本是HEAD^^,依此类推。当然,如果我们要回退100个版本,写100个^显然不太现实,所以Git提供了HEAD~100这样的简写。

要回退到上一个版本,我们可以使用git reset命令。例如:

$ git reset --hard HEAD^

这条命令会将当前版本(即“append GPL”版本)回退到上一个版本(即“add distributed”版本)。--hard参数的作用是丢弃当前版本的所有更改,直接回退到指定版本。这意味着所有未提交的改动都将丢失,所以在使用时要特别小心。

现在,我们可以检查readme.txt的内容,确认是否回退到了正确的版本:

$ cat readme.txt

输出应该是:

Git is a distributed version control system.  
Git is free software.

果然,内容被还原到了“add distributed”版本。

但是,如果我们想继续回退到更早的“wrote a readme file”版本,我们应该怎么做呢?在回退之前,让我们先用git log命令查看一下当前版本库的状态:

$ git log

输出会显示所有提交的历史记录。找到你想要回退到的版本的commit id(例如eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0),然后使用git reset命令回退到该版本:

$ git reset --hard eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0

或者,如果你只记得commit id的前几位,你也可以使用这些前几位数字来指定要回退到的版本。Git会尝试找到与这些数字匹配的最近的commit id。

现在,如果你再次查看readme.txt的内容,你会看到它已经回退到了“wrote a readme file”版本的内容。

需要注意的是,一旦使用git reset --hard命令回退到某个版本,之前的提交记录将不再可见(除非你还没有关闭命令行窗口,并且还能够找到之前的commit id)。这意味着如果你不小心回退到了一个错误的版本,并且没有记录下之前的commit id,那么你可能无法再找回之前的版本了。因此,在使用git reset命令时,一定要小心谨慎。

Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD从指向append GPL

┌────┐
│HEAD│
└────┘
   │
   └──▶ ○ append GPL
        │
        ○ add distributed
        │
        ○ wrote a readme file

改为指向add distributed

┌────┐
│HEAD│
└────┘
   │
   │    ○ append GPL
   │    │
   └──▶ ○ add distributed
        │
        ○ wrote a readme file

然后顺便把工作区的文件更新了。所以你让HEAD指向哪个版本号,你就把当前版本定位在哪。

如果你不小心回退到了一个版本并关掉了电脑,然后后悔想要恢复到新版本,但又找不到新版本的commit id,这时不必过于焦虑。在Git中,你总是有机会恢复到之前的状态。

Git提供了一个非常有用的命令git reflog,它会记录你的每一次命令操作,包括你回退版本的操作。通过git reflog,你可以找到之前版本的commit id,然后再次使用git reset命令恢复到那个版本。

执行git reflog命令后,你会看到类似以下的输出:

e475afc HEAD@{1}: reset: moving to HEAD^  
1094adb (HEAD -> master) HEAD@{2}: commit: append GPL  
e475afc HEAD@{3}: commit: add distributed  
eaadf4e HEAD@{4}: commit (initial): wrote a readme file

这个输出显示了你的提交历史,包括每次提交的commit id和对应的操作描述。从输出中,你可以看到“append GPL”的commit id是1094adb。现在,你可以使用这个commit id来恢复到那个版本:

$ git reset --hard 1094adb

因此,即使你关闭了电脑,也不必担心无法恢复到之前的版本。只要你还记得大致的操作顺序,git reflog命令就能帮助你找到正确的commit id,并让你乘坐“时光机”回到过去。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧