有你在真好 的个人博客
什么是Git-
阅读:2195 添加日期:2021/3/30 17:45:05

什么是Git?

今天我们从以下四个方面介绍Git:

  • What is git

  • Why is git so different

  • How git stores data

  • How branching/merging works for git

1. What is git?

Git是一个开源项目,它自己本身就在github上。Git是一个非常快速的,可扩展的,分布式版本控制(revision control)系统。Git是一个”stupid content tracker”(简单记录内容)。

它的command set非常多,有150多个,不仅有high-level的操作,还有到内部的full access。Git的command分为两种:Porcelain和Plumbing。前者包括很多我们常用的命令,如init, add, commit, branch,后者做一些low-level的工作,如hash-object, update-index, write-tree等。

版本控制(SCM)是指管理软件变化和配置的一个系统。包括管理什么变了以及谁变了它,常用于当有一个很大的版本系统,拥有很多文件并且修改文件人数很多的情况。Rollback是非常关键的事情!

什么是Git?

上图第一行是没有版本控制时文件更改的状态,第二行是使用版本控制时的情况。

举一个写写冲突的例子。当A打开一个文件并做一些修改,B也打开同一文件,做修改并保存。A如何保存文件能保证不丢失B的修改。在Linux系统中,可以用diff和patch。SCM可以大大简化这些工作。

传统的SCM原理图如下:

什么是Git?

所有代码存在Server端。Server端有一个data store,所有的历史都在data store里。所有人都作为Client,从data store里拿远程副本,一个snapshot。在本地更改完后commit上Server。Server端的data store保留原来的数据,并且将新数据改写为头部。在每次commit前,re-sync数据。

这种系统的不足之处在于,如果re-sync时,snapshot的版本不是Repo上最新的版本时,Server端可能丢失数据。因为commit前,所有改动都在Client端,就会出现Single point of failure。比如Client端remove了一个文件,如果文件有本地更改并且没有及时commit到Server,更改就会丢失。或者当Server有failure且没有备份,那么数据历史信息将丢失。同时有些操作需要连网,导致很慢,比如svn当你想看version history或者想去做svn diff(看本地更改的内容是什么)的时候,会需要联网。

下图是传统SCM的workflow:

什么是Git?

2. Why git is different?

最大的不同在于Git是分布式的。

1) What does distributed even mean?

分布式在于不把所有数据存在同一地方。

下图是git的原理图:

什么是Git?

不同于之前的方式,git在Client端也有database,可以认为是在本地的一个缓存。每个clone不是snapshot而是数据的全部备份。在最初的clone之后,几乎所有的操作都是本地的。

好处是没有Single point of failures。一是本地有database随时备份可以减少数据丢失。由于引入了local db和local commit的概念随时commit成为了可能。比如之前提到不小心rm了文件的情况,在git里面可以由本地的db回复。二是当Server出错时,可以把Client数据reset成Server数据。Git非常快,因为所有数据在本地都可以读取,减少带宽。Git是可扩展的,branch的数量可以非常多。

2) What is git’s Version Database?

Version Database本质上是一个文件系统(content addressable filesystem)。以key-value的形式存储数据。Key使用SHA-1 hash,有20 bytes,40 hex。Value是binary files,占用空间更小,包括三种:

(1)Commits:真正的 git commits。commit就是一个snapshot

(2)Trees:Directories(structure of file system)

(3)Blobs:content of files/data

3. How git stores data

下图是一个简单git使用流程:

什么是Git?

第一个init新建一个repository。产生一个.git目录,这个目录结构如下图:

什么是Git?

Git里一个重要的概念是Stage area。如下图所示:

什么是Git?

Git在add的时候没有把文件加入repository,但是Blob已经存在了。文件只有在Staging area的时候,才能进行commit工作。Staging area是一个index文件。

下图是Git在commit时候的snapshot:

什么是Git?

当commit时,project的根目录被hash成了一个tree。有我们创建的文件Hello.txt,它变成一个Blob。commit是整个snapshot的入口。

3) What is missing?

如何找到一个commit?Refs!

什么是Git?

git HEAD指的是ref,它是一个file,file里存的是一个commit的hash。从hash可以找到commit。

index是一个线性的排序结构,按照文件夹目录名排序。而tree就是树状结构。commit的时候改变tree,不commit的时候tree没有变化。

当对代码进行更新并再进行一次commit时,如下图示:

什么是Git?

什么是Git?

4. How branching/merging works for git?

1)What is branch?

Branch只是一个41 byte大小的文件。新建一个branch时只有refs里的head增加了一个41 byte的文件,其他事情都没有发生。

什么是Git?

什么是Git?

2) What is happening on merge?

首先从master和另一个要merge的branch(比如feature)里找到共同的部分

什么是Git?

接下来比较找到的两个commit,只需找到有变化的部分,改变真正的文件,同时考虑conflict的问题:

什么是Git?

最后生成一个commit,这个commit有两个parent指针:

什么是Git?

最后我们再回顾一下之前提到的那句话,现在会有更深刻的理解:

什么是Git?

本文作者:Shaoke Xu, 更多精彩内容,欢迎访问官网 BitTiger.io 或关注 “论码农的自我修养” 微信公众号:bit_tiger

ICP备案号:苏ICP备14035786号-1 苏公网安备 32050502001014号