转载:版本回退

现在,你已经学会了修改文件,然后把修改提交到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. C# 结构与类的区别

    一.定义方式 定义结构: struct PointStruct //默认的访问权限是 public { public int X { get; set; } public int Y { get; s ...

  2. vue2.0自学笔记

    前言: 一.优点: 轻量级.高效率.上手快.简单易学.文档全面而简洁 二.功能: 1.模板渲染 2.模块化 3.扩展功能:路由.Ajax 三.课程包含: 1.Vue实例 2.Vue组件 3.Vue指令 ...

  3. .net项目dll内嵌加载

    1.将dll文件作为嵌入资源添加到项目: 2.程序入口增加以下代码: public partial class App : Application { private void Application ...

  4. ES5和ES6那些你必须知道的事儿(三)

    ES5和ES6那些你必须知道的事儿 ES6新增的东西 一.块级作用域:关键字let,常量const let与var的区别: a.不会进行变量声明提升 b.变量不允许被重复定义 c.变量不允许被删除 d ...

  5. As The End of The Year Approaches,The Weighted Blanket Season Begins

    Weight blankets are well known for anxiety, insomnia, depression and so on. It is physical therapy, ...

  6. 软件151 王楚博 struts

    一.下载Struts 建立web项目,给项目添加外部引用包(project-properties-Java Build Path-Add External Jars...).添加的包有:commons ...

  7. python 生成器(generator)的生成方式

    generator包括生成器和带yield的generator函数. 写了一个生成杨辉三角的小例子: # -*- coding:utf-8 -*- def triangles(): l = [1] w ...

  8. Exploit-Exercises nebule 旅行日志(六)

    接着上次的路程继续在ubuntu下对漏洞的探索练习,这次是level05了 先看下level05的问题描述: 从level05的描述上看,是/home/flag05目录的权限有漏洞,看来多半是又跟fl ...

  9. MySQL data sync to Oracle with OGG(Remote Delivery)

    MySQL to Oracle with OGG 1. Install MySQL: yum install mysql-community-server [root@localhost ~]#  y ...

  10. [面经]杭州某初创公司FPGA工程师实习

    面试时间:2017年8月17日 面试时长:约1小时 面试形式:面对面 面试公司:杭州某初创公司,致力于开发VR相关产品 面试职位:FPGA工程师(实习) 面试官:公司现任FPGA开发工程师,双控硕士毕 ...