Git 学习(四)操作修改和版本穿梭
Git 学习(四)操作修改和版本穿梭
之前的章节,已介绍了本地Git库创建、暂存区增、删、改,以及提交版本库;可回顾下命令操作: git add 和 git commit。
光有之前章节的操作,Git 显然不能满足版本控制的需求。所谓的版本控制,可理解为文件夹的时间机,即从创建该文件夹伊始,所有文件提交操作都将被记录版本库,且可以随意穿梭版本(回退至昨日的版本,或甚至N年前)。
本文就此具体说明Git是如何管理修改、撤销修改以及在各个版本间穿梭的。
管理修改
为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件。为达成这一目的,暂存区存在的意义就在于此。
此外,先依据 .git/index (暂存区文件)中记录的时间戳、长度等信息判断工作区文件是否改变。如果工作区的文件时间戳改变,说明文件的内容可能被改变了,需要要打开文件,读取文件内容,和更改前的原始文件相比较,判断文件内容是否被更改。如果文件内容没有改变,则将该文件新的时间戳记录到 .git/index 文件中。因为判断文件是否更改,使用时间戳、文件长度等信息进行比较要比通过文件内容比较要快的多,所以 Git 这样的实现方式可以让工作区状态扫描更快速的执行,这也是 Git 高效的因素之一。
git/index 实际上就是一个包含文件索引的目录树,像是一个虚拟的工作区。在这个虚拟工作区的目录树中,记录了文件名、文件的状态信息(时间戳、文件长度等),文件的内容并不存储其中,而是保存在 Git 对象库(.git/objects)中,文件索引建立了文件和对象库中对象实体之间的对应。下面这个图展示了工作区、版本库中的暂存区和版本库之间的关系。

工作区、版本库、暂存区 操作原理图
在这个图中,我们可以看到部分 Git 命令是如何影响工作区和暂存区(stage/index)的:
图中左侧为工作区,右侧为版本库。在版本库中标记为 "index" 的区域是暂存区(stage/ndex),标记为 "master" 的是 master 分支所代表的目录树
图中我们可以看出此时 "HEAD" 实际是指向 master 分支的一个“游标”。所以图示的命令中出现 HEAD 的地方可以用 master 来替换
图中的 objects 标识的区域为 Git 的对象库,实际位于 ".git/objects" 目录下
当对工作区修改(或新增)的文件执行 "git add ..." 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID 被记录在暂存区的文件索引中。
当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树
当执行 "git reset HEAD" 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响
当执行 "git rm --cached <file>" 命令时,会直接从暂存区删除文件,工作区则不做出改变
当执行 "git checkout -- <file>" 命令时,会将文件在工作区的修改撤销
当执行 "git checkout HEAD ." 或者 "git checkout HEAD <file>" 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。
上文内容其实是第三章: Git 学习(三)本地仓库操作——git add & commit 工作区与版本库的补充说明,原理图中提及的部分命令还未介绍,可先大致浏览,完全看完下文后再理解上图(该图很重要)。
需要注意:工作区其实与Git库是分离的,我们在工作区进行的修改,如果不add到暂存区,commit提交并不会提交版本(再次重申,commit 提交修改仅针对暂存区)。
这边所说的修改,包括文件本身的修改(删行、加行、改内容等),而创建新文件或删除,也算一个修改。
修改撤销
这边,介绍下暂存区撤销修改的命令:
git checkout -- <file1> <file2> ... 将文件在工作区的修改全部撤销,可多个,空格分隔
git checkout -- file命令中的 "--" 很重要,没有"--",就变成了切换分支的命令,切换分支命令将在以后章节介绍。
举几个具体示例来说明以上命令的用法,初始化空git库,若你先创建了 1.txt 并将其 git add,你在工作区修改了 1.txt 文件,但发现修改错了,需要撤销修改至当时 git add 的情况
git status 可见如下提示
git checkout -- 1.txt 后,再次打开 1.txt,发现其中的内容被撤销修改了,即内容为 111;
若工作区删除了 1.txt,但现在又想撤销删除,也可操作 git checkout -- 1.txt ,此时查看工作区,可发现 1.txt 被恢复了。
版本穿梭
仅仅针对工作区的修改撤销是远远不够的,需要在所有版本库中任意切换;版本是针对 commit 操作而言的,每次 commit 成功后,都会自动生成版本号。
git log 显示当前分支提交版本库的日志
git log 该命令很常用,可显示提交日志信息(当前版本库,可加参数,help查询具体);上图可见茶色字体显示了一大串类似
每提交一个新版本,实际上Git就会把它们自动串成一条时间线。如果使用可视化工具查看Git历史,就可以更清楚地看到提交历史的时间线:
git reset --hard <revision> 重置至某一版本(强制,暂存区和工作区均重置)
必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交,上一个版本就是HEAD^,上上一个版本就是HEAD^^ ...
如上,我们要把当前版本回退到最新版本,就可以使用命令行 git reset --hard ,若使用命令行 git reset --hard HEAD^,则回滚为上一版本,此时 git log 仅显示了当前版本及其之前的信息
命令可输入版本号,前几位即可(通常前7位);显然,若回滚了昨天的版本后,又反悔了的这种情况还是时有发生的,这时,就需要输版本号了;然则,版本号忘了怎么办。。这时,需要另一个命令帮助:
git reflog 显示操作的日志
该命令可显示操作日志,且显示了对应的版本号及信息,可查询到之前的版本号并再次回滚, 如 git reset --hard 6de39b3 。
Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD指向改变
改为指向 2:
然后顺便把工作区、暂存区文件更新了。
Git 学习(四)操作修改和版本穿梭的更多相关文章
- git学习(四):理解git暂存区(stage)
与一般的版本管理不同的是,git在提交之前要将更改通过git add 添加到暂存区才能提交(git commit).即使是已经交给了git来管理的文件也是如此.这里继续学习git的暂存区. 通过git ...
- Git学习-->GitLab如何修改时区?
一.背景 今天有同事在GitLab上查看时间的时候,发现GitLab上显示的时间和提交的时间不一致. 本地时间现在为:2017-11-28 11:43 查看本地代码提交的时间为:2017-11-28 ...
- git 学习笔记 ---撤销修改
自然,你是不会犯错的.不过现在是凌晨两点,你正在赶一份工作报告,你在readme.txt中添加了一行: $ cat readme.txt Git is a distributed version co ...
- 三、git学习之——管理修改、撤销修改、删除文件
一.管理修改 现在,假定你已经完全掌握了暂存区的概念.下面,我们要讨论的就是,为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件. 你会问,什么是修改?比如你新增了一行, ...
- Git学习(二)——创建版本库、查看与回退版本
一.创建版本库 版本库,又名仓库(Repository),可以简单理解为一个目录,这个目录里的所有文件可以被Git管理起来,每个文件的修改.删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者将来某 ...
- Git学习笔记(2)——版本的回退,和暂存区的理解
本文主要记录了版本的回退,以及工作区,暂存区概念的理解. //开始之前,先回顾上次的内容,修改文件如下,并提交到版本库. Git is a distributed version control sy ...
- git学习——<四>git版本管理
一.git版本管理的优势 都说git比svn强大,强大在哪呢? 首先,从部署上说:svn.cvs都是集中式的,一台服务器上部署服务,所有客户端编写的代码都要提交到该服务器上.git是分布式的,所有人都 ...
- git学习笔记 ---管理修改
现在,假定你已经完全掌握了暂存区的概念.下面,我们要讨论的就是,为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件. 你会问,什么是修改?比如你新增了一行,这就是一个修改 ...
- git学习(四) git log操作
git log操作 log命令的作用:用于查看git的提交历史: git log命令显示的信息的具体含义: commit SHA-1 校验和 commit id Author 作者跟邮箱概要信息 D ...
随机推荐
- hdoj1863 畅通工程(Prime || Kruskal)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1863 思路 最小生成树问题,使用Prime算法或者Kruskal算法解决.这题在hdoj1233的基础 ...
- SpringBoot常用配置
前言:springboot集成了主流的第三方框架,但是需要使用springboot那一套配置方式.但是我这里只列举了非常非常常用的,可以看已发的几篇博客,慢慢会补充.当然官方文档里也有相应的配置,可惜 ...
- IDEA导入eclipse项目并部署运行完整步骤(转发)
首先说明一下:idea里的project相当于eclipse里的workspace,而idea里的modules相当于eclipse里的project 1.File-->Import Proje ...
- redis 主要数据类型及使用
1.类型 redis 的主要数据类型: 1.1 string 字符串类型<*是其它4种类型的基础> 1.2 hash 散列类型 1.3 list 列表类型 1.4 set 集合类型 1.5 ...
- html5那些事儿
一.优势1.标签的改变:<header>,<footer>,<dialog>,<aside>,<figure>,<section> ...
- 机器学习之路:python 字典特征提取器 DictVectorizer
python3 学习使用api 将字典类型数据结构的样本,抽取特征,转化成向量形式 源码git: https://github.com/linyi0604/MachineLearning 代码: fr ...
- ROS知识(8)----CMakeLists.txt文件编写的理解
ROS(Indigo)编程必须要理解CMakeList.txt的编写规则,教程地址:catkin/CMakeLists.txt,官网有相关的教程,中文的翻译版本写的很不错,教程地址:ROS中的CMak ...
- DOM-XML(解析与创建)
/** * 读取(解析)xml文件 * @author Administrator * */ public class DOMRead { public static void main(String ...
- centos 6.5安装rvm 配置 Ruby开发环境
我是用ruby写测试脚本用 安装rvm也是费了好大劲 英文不易看懂 ,是个硬伤! rvm是ruby的版本管理工具 还可对ruby进行 安装 卸载 等 1.安装 curl # sudo yum ...
- Ubuntu16.04中安装stlink驱动
系统环境: Vmware12, Ubuntu16.04 Stlink version:v1.4.0 一.安装依赖包: sudo apt-get install libusb-1.0 sudo apt- ...