转载:版本回退

现在,你已经学会了修改文件,然后把修改提交到Git版本库,现在,再练习一次,修改readme.txt文件如下:

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

然后尝试提交:

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

像这样,你不断对文件进行修改,然后不断提交修改到版本库里,就好比玩RPG游戏时,每通过一关就会自动把游戏状态存盘,如果某一关没过去,你还可以选择读取前一关的状态。有些时候,在打Boss之前,你会手动存盘,以便万一打Boss失败了,可以从最近的地方重新开始。Git也是一样,每当你觉得文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit恢复,然后继续工作,而不是把几个月的工作成果全部丢失。

现在,我们回顾一下readme.txt文件一共有几个版本被提交到Git仓库里了:

版本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: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:06:15 2018 +0800 append GPL commit e475afc93c209a690c39c13a46716e8fa000c366
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:03:36 2018 +0800 add distributed commit eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 20:59:18 2018 +0800 wrote a readme file

git log命令显示从最近到最远的提交日志,我们可以看到3次提交,最近的一次是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需要用这么一大串数字表示呢?因为Git是分布式的版本控制系统,后面我们还要研究多人在同一个版本库里工作,如果大家都用1,2,3……作为版本号,那肯定就冲突了。

每提交一个新版本,实际上Git就会把它们自动串成一条时间线。如果使用可视化工具查看Git历史,就可以更清楚地看到提交历史的时间线:

好了,现在我们启动时光穿梭机,准备把readme.txt回退到上一个版本,也就是add distributed的那个版本,怎么做呢?

首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交1094adb...(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100

现在,我们要把当前版本append GPL回退到上一个版本add distributed,就可以使用git reset命令:

$ git reset --hard HEAD^
HEAD is now at e475afc add distributed

--hard参数有啥意义?这个后面再讲,现在你先放心使用。

看看readme.txt的内容是不是版本add distributed

$ cat readme.txt
Git is a distributed version control system.
Git is free software.

果然被还原了。

还可以继续回退到上一个版本wrote a readme file,不过且慢,然我们用git log再看看现在版本库的状态:

$ git log
commit e475afc93c209a690c39c13a46716e8fa000c366 (HEAD -> master)
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:03:36 2018 +0800 add distributed commit eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 20:59:18 2018 +0800 wrote a readme file

最新的那个版本append GPL已经看不到了!好比你从21世纪坐时光穿梭机来到了19世纪,想再回去已经回不去了,肿么办?

办法其实还是有的,只要上面的命令行窗口还没有被关掉,你就可以顺着往上找啊找啊,找到那个append GPLcommit id1094adb...,于是就可以指定回到未来的某个版本:

$ git reset --hard 1094a
HEAD is now at 83b0afe append GPL

版本号没必要写全,前几位就可以了,Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了。

再小心翼翼地看看readme.txt的内容:

$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.

果然,我胡汉三又回来了。

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

改为指向add distributed

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

现在,你回退到了某个版本,关掉了电脑,第二天早上就后悔了,想恢复到新版本怎么办?找不到新版本的commit id怎么办?

在Git中,总是有后悔药可以吃的。当你用$ git reset --hard HEAD^回退到add distributed版本时,再想恢复到append GPL,就必须找到append GPL的commit id。Git提供了一个命令git reflog用来记录你的每一次命令:

$ 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

终于舒了口气,从输出可知,append GPL的commit id是1094adb,现在,你又可以乘坐时光机回到未来了。

小结

现在总结一下:

  • HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id

  • 穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。

  • 要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。

git教程:版本退回的更多相关文章

  1. 7.Git的版本退回

    现在,你已经学会了修改文件,然后把修改提交到Git版本库,现在,再练习一次,修改readme.txt文件如下: Git is a distributed version control system. ...

  2. 史上最浅显易懂的Git分布式版本控制系统教程

    从零起步的Git教程,让你无痛苦上手世界上最流行的分布式版本控制系统Git! 既然号称史上最浅显易懂的Git教程,那这个教程有什么让你怦然心动的特点呢? 首先,本教程绝对面向初学者,没有接触过版本控制 ...

  3. 分布式版本控制系统 Git 教程

    简介 Git 是什么? Git 是一个开源的分布式版本控制系统. 什么是版本控制? 版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统. 什么是分布式版本控制系统? 介绍分布 ...

  4. Git 版本退回commit

    有的时候错误提交了commit,需要版本退回. 先用git log查看一下节点版本号commit_id $ git log 再用git reset退回 $ git reset -soft commit ...

  5. 简明git教程(单人版本)

    最近开始写一个比较大的东西,所以需要用到git,之前一直在用金山快盘和乌龟搭建的SVN,最近想尝试一下git 1.安装 Ubuntu: sudo apt-get install git 老版本的Ubu ...

  6. Git教程之版本回退(4)

    现在,我们已经学会了修改文件,然后把修改提交到Git版本库,现在再次修改readme.txt文件如下:

  7. git教程--git版本库的使用

    向版本控制器提交文件 我们已经成功地添加并提交了一个readme.txt文件,现在,是时候继续工作了,于是,我们继续修改readme.txt文件,改成如下内容: Git is a distribute ...

  8. git学习笔记 ---版本退回

    我们已经成功地添加并提交了一个readme.txt文件,现在,是时候继续工作了,于是,我们继续修改readme.txt文件,改成如下内容: Git is a distributed version c ...

  9. Git使用手册/Git教程:git fetch 将远程仓库的分支及分支最新版本代码拉取到本地

    相关文章: 关于验证是否存在ssh配置以及生成SSH Key的方法可以参照文章:Git使用手册:生成SSH Key 关于SSH Key的使用和公钥在gitHub.gitLab的配置等,请参考文章:Gi ...

随机推荐

  1. vue-element-ui之弹窗重置

    遇到列表中需要给弹框赋默认值并且关闭后需要清空数据+清除验证时可以这么写:

  2. mac下idea搭建maven项目的一些问题总结

    1.关于版本 目标原版与原发行版本不一致 <build> <finalName>comment</finalName> <plugins> <pl ...

  3. Java 面向对象 知识点基础浅谈

    1.类和对象的关系 类是一个抽象的模板,对象是根据模板制造出来的,只有类建立之后,对象才可以在类中实例化对象.举个例子讲:我要用黄金浇筑一块砖,我会在一个模型里进行,这样才能有砖的形状,那模型即是类, ...

  4. [CentOS] 环境变量设置的三种方法

    在CentOS系统中添加环境变量的方法有几种,推荐第三种方法.这里以添加 TexLive 2017 的环境变量为例进行说明. 1. 修改  ~/.bash_profile  文档,在文末添加以下代码: ...

  5. C#UDP广域网,局域网通信-原理分析

    一.UDP局域网通信. 这个比较简单,关于局域网中的2台或者更多的计算机之间的UDP通信,网络上一大把,直接复制粘贴就可以使用,原理也非常简单.所以,本文不做详细介绍. 二.UDP广域通信(包括路由器 ...

  6. numpy通用函数

    numpy的通用函数可以对数组进行向量化操作,可以提高数组元素的重复计算的效率. 一.numpy的算数运算符都是对python内置符的封装 算数运算符 >>> import nump ...

  7. 前端基础之DOM和BOM

    前端基础之DOM和BOM JavaScript分为 ECMAScript,DOM,BOM. BOM(Browser Object Model)是指浏览器对象模型,它使 JavaScript 有能力与浏 ...

  8. [Codeforces543D]Road Improvement

    Problem 刚开始每条边都是坏的,现在要选取一个点使得其他点到这个点的路径上最多只有一条坏路,问至少要修好多少条边 Solution 如果以1为根,那么是个简单的树形DP 设根从u转移到v,那么u ...

  9. java第七次课堂笔记

  10. 2072. Kirill the Gardener 3

    http://acm.timus.ru/problem.aspx?space=1&num=2072 回忆一下 #include <iostream> #include <st ...