Git的思想和基本工作原理

转载自:http://www.nowamagic.net/academy/detail/48160210#

在开始学习 Git 的时候,请不要尝试把各种概念和其他版本控制系统(诸如 Subversion 和 Perforce 等)相比拟,否则容易混淆每个操作的实际意义。Git 在保存和处理各种信息的时候,虽然操作起来的命令形式非常相近,但它与其他版本控制系统的做法颇为不同。理解这些差异将有助于你准确地使用 Git 提供的各种工具。

直接记录快照,而非差异比较

Git 和其他版本控制系统的主要差别在于,Git 只关心文件数据的整体是否发生变化,而大多数其他系统则只关心文件内容的具体差异。这类系统(CVS,Subversion,Perforce,Bazaar 等等)每次记录有哪些文件作了更新,以及都更新了哪些行的什么内容:

其他系统在每个版本中记录着各个文件的具体差异

Git 并不保存这些前后变化的差异数据。实际上,Git 更像是把变化的文件作快照后,记录在一个微型的文件系统中。每次提交更新时,它会纵览一遍所有文件的指纹信息并对文件作一快照,然后保存一个指向这次快照的索引。为提高性能,若文件没有变化,Git 不会再次保存,而只对上次保存的快照作一链接。Git 的工作方式就如下图所示。

Git 保存每次更新时的文件快照

这是 Git 同其他系统的重要区别。它完全颠覆了传统版本控制的套路,并对各个环节的实现方式作了新的设计。Git 更像是个小型的文件系统,但它同时还提供了许多以此为基础的超强工具,而不只是一个简单的 VCS。稍后会讨论 Git 分支管理的时候,我们会再看看这样的设计究竟会带来哪些好处。

近乎所有操作都是本地执行

在 Git 中的绝大多数操作都只需要访问本地文件和资源,不用连网。但如果用 CVCS 的话,差不多所有操作都需要连接网络。因为 Git 在本地磁盘上就保存着所有当前项目的历史更新,所以处理起来速度飞快。

举个例子,如果要浏览项目的历史更新摘要,Git 不用跑到外面的服务器上去取数据回来,而直接从本地数据库读取后展示给你看。所以任何时候你都可以马上翻阅,无需等待。如果想要看当前版本的文件和一个月前的版本之间有何差异,Git 会取出一个月前的快照和当前文件作一次差异运算,而不用请求远程服务器来做这件事,或是把老版本的文件拉到本地来作比较。

用 CVCS 的话,没有网络或者断开 VPN 你就无法做任何事情。但用 Git 的话,就算你在飞机或者火车上,都可以非常愉快地频繁提交更新,等到了有网络的时候再上传到远程仓库。同样,在回家的路上,不用连接 VPN 你也可以继续工作。换作其他版本控制系统,这么做几乎不可能,抑或非常麻烦。比如 Perforce,如果不连到服务器,几乎什么都做不了(默认无法发出命令 p4 edit file 开始编辑文件,因为 Perforce 需要联网通知系统声明该文件正在被谁修订。但实际上手工修改文件权限可以绕过这个限制,只是完成后还是无法提交更新。);如果是 Subversion 或 CVS,虽然可以编辑文件,但无法提交更新,因为数据库在网络上。看上去好像这些都不是什么大问题,但实际体验过之后,你就会惊喜地发现,这其实是会带来很大不同的。

时刻保持数据完整性

在保存到 Git 之前,所有数据都要进行内容的校验和(checksum)计算,并将此结果作为数据的唯一标识和索引。换句话说,不可能在你修改了文件或目录之后,Git 一无所知。这项特性作为 Git 的设计哲学,建在整体架构的最底层。所以如果文件在传输时变得不完整,或者磁盘损坏导致文件数据缺失,Git 都能立即察觉。

Git 使用 SHA-1 算法计算数据的校验和,通过对文件的内容或目录的结构计算出一个 SHA-1 哈希值,作为指纹字符串。该字串由 40 个十六进制字符(0-9 及 a-f)组成,看起来就像是:

1 24b9da6552252987aa493b52f8696cd6d3b00373

Git 的工作完全依赖于这类指纹字串,所以你会经常看到这样的哈希值。实际上,所有保存在 Git 数据库中的东西都是用此哈希值来作索引的,而不是靠文件名。

多数操作仅添加数据

常用的 Git 操作大多仅仅是把数据添加到数据库。因为任何一种不可逆的操作,比如删除数据,都会使回退或重现历史版本变得困难重重。在别的 VCS 中,若还未提交更新,就有可能丢失或者混淆一些修改的内容,但在 Git 里,一旦提交快照之后就完全不用担心丢失数据,特别是养成定期推送到其他仓库的习惯的话。

这种高可靠性令我们的开发工作安心不少,尽管去做各种试验性的尝试好了,再怎样也不会弄丢数据。至于 Git 内部究竟是如何保存和恢复数据的,我们会在后面讨论 Git 内部原理时再作详述。

文件的三种状态

好,现在请注意,接下来要讲的概念非常重要。对于任何一个文件,在 Git 内都只有三种状态:已提交(committed),已修改(modified)和已暂存(staged)。已提交表示该文件已经被安全地保存在本地数据库中了;已修改表示修改了某个文件,但还没有提交保存;已暂存表示把已修改的文件放在下次提交时要保存的清单中。

由此我们看到 Git 管理项目时,文件流转的三个工作区域:Git 的工作目录,暂存区域,以及本地仓库。

工作目录,暂存区域,以及本地仓库

每个项目都有一个 Git 目录(如果 git clone 出来的话,就是其中 .git 的目录;如果 git clone --bare 的话,新建的目录本身就是 Git 目录。),它是 Git 用来保存元数据和对象数据库的地方。该目录非常重要,每次克隆镜像仓库的时候,实际拷贝的就是这个目录里面的数据。

从项目中取出某个版本的所有文件和目录,用以开始后续工作的叫做工作目录。这些文件实际上都是从 Git 目录中的压缩对象数据库中提取出来的,接下来就可以在工作目录中对这些文件进行编辑。

所谓的暂存区域只不过是个简单的文件,一般都放在 Git 目录中。有时候人们会把这个文件叫做索引文件,不过标准说法还是叫暂存区域。

基本的 Git 工作流程如下:

  1. 在工作目录中修改某些文件。
  2. 对修改后的文件进行快照,然后保存到暂存区域。
  3. 提交更新,将保存在暂存区域的文件快照永久转储到 Git 目录中。

所以,我们可以从文件所处的位置来判断状态:如果是 Git 目录中保存着的特定版本文件,就属于已提交状态;如果作了修改并已放入暂存区域,就属于已暂存状态;如果自上次取出后,作了修改但还没有放到暂存区域,就是已修改状态。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499862.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java后端获取客户端(用户)真实ip,原理

java后端获取客户端真实ip,原理: 一般都是下面代码中的做法:但很多人只知道这样能拿到,稍微有改动就不知道怎么办了 看看网上的各种说法,接下来容我一一讲解,如有纰漏,敬请指正。 public sta…

kafka入门:简介、使用场景、设计原理、主要配置及集群搭建

本文转自:http://www.aboutyun.com/thread-9341-1-1.html一、入门1、简介Kafka is a distributed,partitioned,replicated commit logservice。它提供了类似于JMS的特性,但是在设计实现上完全不同,此外它并不是JMS规范的实现。kafka对消息保存…

git大小写解决

git大小写解决 git reset --hard head git的回退操作 git config --get core.ignorecase 查看git忽略大小写的状态,true就是忽略大小写,false就是不忽略大小写 git config core.ignorecase false 更改git为不忽略大小写 情景1:(…

深入理解Hadoop集群和网络

云计算和Hadoop中网络是讨论得相对比较少的领域。本文原文由Dell企业技术专家Brad Hedlund撰写,他曾在思科工作多年,专长是数据中心、云网络等。文章素材基于作者自己的研究、实验和Cloudera的培训资料。 本文将着重于讨论Hadoop集群的体系结构和方法&am…

Method-Swizzling实战-实现iOS原生网络请求性能采集

一、方法交换实现步骤(实例方法和类方法处理逻辑类似) 1.检查原类(要被替换方法的类)的原实例方法是否存在,如果不存在,则不交换;2.检查新类(最终被使用的方法所在的类)的…

java8新特性(1)--- lambda表达式

java8新特性(1)— lambda表达式 函数式编程,简化开发 新增语法(->) package com.common.jdk8;// 试想,如果在jdk1.7中,我们要实现基于这个接口的加法运算,一般会这样 // 先创建…

iOS中WebKit框架应用与解析

一、引言 在iOS8之前,在应用中嵌入网页通常需要使用UIWebView这样一个类,这个类通过URL或者HTML文件来加载网页视图,功能十分有限,只能作为辅助嵌入原生应用程序中。虽然UIWebView也可以做原生与JavaScript交互的相关处理&#xf…

java8新特性(2)--- 方法引用

java8新特性(2)— 方法引用 新增语法双冒号(::) package com.common.jdk8;import java.util.Arrays; import java.util.List;//方法引用 public class Jdk8Test2 {public static void main(String[] args) {//构造器引用&#x…

让WKWebView支持NSURLProtocol

NSURLProtocol能够拦截UIWebView内所有的请求,但是WKWebView 中的请求却完全不遵从这一规则,只是象征性调用canInitWithRequest方法,之后的整个请求流程似乎就与 NSURLProtocol 完全无关了。使我一度认为WKWebView请求不遵守NSURLProtocol协议…

java8新特性(3)--- 函数式接口

java8新特性(3)— 函数式接口 有且仅有一个抽象方法 package com.common.jdk8;import java.util.Arrays; import java.util.List; import java.util.function.Predicate;// 函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,…

Git仓库迁移,包括所有的分支、标签、日志

仅三行命令即可完成: git clone --bare http://域名/分组/仓库名称.git cd 仓库名称.git git push --mirror http://新域名/新分组/新仓库名称.git

java8新特性(4)— Stream流

java8新特性(4)— Stream流 遍历集合更强大 package com.common.jdk8;import java.util.*; import java.util.stream.Collectors;//Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。 //Stream 使用一种类似用…

二、工作量证明链-区块链技术的雏形

用算法解决难题——区块链技术的雏形 构造出一个完美的、可以解决问题的“拜占庭容错系统”是一个不小的挑战。而且构造出来以后,其是否真的有效,能否经得起时间的考验与各方的质疑,这些都关乎着这个系统未来的命运与其创造群体的声誉。 2008…

CocoaPods通过网络代理执行资源更新

一、使用网络代理 首先在电脑设置网络代理配置。 二、设置git的http、https代理 1.查看git是否已经设置网络代理 首先可以先查本地的git配置有没有配置http/https代理:git config --global -e 如果没有看到 [http]proxy和 [https]proxy就代表没有设置http/http…

java8新特性(5)— Optional 类

java8新特性(5)— Optional 类 空指针解决方案 package com.common.jdk8;import java.util.Optional;//Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。 //Optional 是个容器&…

五、工作量证明链解决拜占庭将军问题之模拟程序(Objective-C)

一、概述: 此程序用来模拟工作量证明链如何解决拜占庭将军问题,使用Objective-C语言,需要使用Xcode开发工具运行并执行演示,演示结果打印在Xcode控制台。 二、示例程序: 程序下载地址:工作量证明链解决拜…

java8新特性(6)— 日期与时间

java8新特性(6)— 日期与时间 全新的日期与时间处理 package com.common.jdk8;import java.time.*;//Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理。 //在旧版的 Java 中,日期时间 API 存在诸多问题&#xff…

六、区块链主流共识算法浅析

转自:http://www.cocoachina.com/cms/wap.php?actionarticle&id22240。 一、概述: 1.工作量证明(Proof of Work): 通过所有节点的工作量竞争来达成一致。竞争的是运算力。 2.权益证明(Proof of S…

java8新特性(7)— Base64

java8新特性(7)— Base64 新增Base64工具类 package com.common.jdk8;import java.io.UnsupportedEncodingException; import java.util.Base64; import java.util.UUID;//在Java 8中,Base64编码已经成为Java类库的标准。 //Java 8 内置了 …

修改git历史提交的commit信息

本文是基于idea的操作,亲测可用 前言: 很多公司都会自定义 Git - 使用强制策略,那么他的commit信息就会有固定的格式,一旦不是这个格式,就会出现push失败 但是push失败,很多也只在dev和master分支做强制限…