码迷,mamicode.com
首页 > 其他好文 > 详细

什么是Git?内部剖析

时间:2016-06-18 01:38:46      阅读:283      评论:0      收藏:0      [点我收藏+]

标签:git

Git:是目前世界上最先进的分布式版本控制系统(没有之一).

Git功能:进行版本控制管理

版本:一个文件每次保存后的样本。

  1. 如果你修改了一个文件,而你又不确定原来的版本以后可能用到,所以你就会保存原来的版本和新生成的版本,再次修改第二版本的时候,你又会生成一个版本,于是,关于一个文件,你有了每个版本的备份。如此一来,你管理肯定是极不方便的。

  2. 有些部分需要你的财务同事帮助填写,于是你把文件Copy到U盘里给她(也可能通过Email发送一份给她),然后,你继续修改Word文件。一天后,同事再把Word文件传给你,此时,你必须想想,发给她之后到你收到她的文件期间,你作了哪些改动,得把你的改动和她的部分合并,真困难。

集中式版本控制系统:

技术分享

得出:集中式版本控制必须联网使用版本控制,当文件较大时,易受网络状态影响下载,上传速度。

分布式版本控制系统:

分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。既然每个人电脑上都有一个完整的版本库,那多个人如何协作呢?比方说你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。

和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了。

在实际使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。

Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!一个月之内,Linux系统的源码已经由Git管理了!2008年,GitHub网站上线了,它为开源项目免费提供Git存储,无数开源项目开始迁移至GitHub,包括jQuery,PHP,Ruby等等。

用户注册一个账号就能将本地的Git交给远程GitHub仓库来保存了,只要有网,随时随地可以从远程端获取或者推送自己的文件数据,这样就更加凸显了安全高效的优势。

即作为服务器。

技术分享

Git思想是:它管理的是文件的修改,而不是文件本身,所以主题应该围绕如何来存储并管理文件的修改来展开。

接下来就随着git的使用让我们来了解它是如何管理的。

  1. 安装Git

    sudo apt-get install git-core

  2. 设置用户


  3.  git config --global user.name "Your Name"
  4. $ git config --global user.email "email@example.com"

Git是分布式版本控制系统,所以,每个机器都必须自报家门:你的名字和Email地址。你也许会担心,如果有人故意冒充别人怎么办?这个不必担心,首先我们相信大家都是善良无知的群众,其次,真的有冒充的也是有办法可查的。

注意git config命令的--global参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。

3. 创建版本库

 版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。新建文件夹,以后这个目录就是你本地的版本库,这个版本库可以是空的,也可以使你以前使用的一个目录。

 通过git init命令把这个目录变成Git可以管理的仓库:

接下来你会发现你的文件夹下多了一个.git隐藏文件。

如下是.git里面的内容。

技术分享

这个目录下,除了.git目录外的都算作工作区。

objects目录存放的是实际的文件,当git add命令执行的时候,文件已经被存到了objects目录下。

.git/objects目录下的对象都有一个40位的id,前两位作为目录名,后38位作为文件名

技术分享

技术分享

2.index是一个索引文件。存放的是暂存区的整个目录树的信息,并且为目录树中的每个文件都保存了时间戳和长度。

当git add 将某个文件添加到暂存区的时候,index文件中添加了这个文件的基本信息。

当我们修改了工作区的某个文件(比如用touch config.js修改时间戳信息),这会导致该文件的时间戳发生变化,而index里面存放的仍然是旧的信息。

此时当我们执行git status命令来检查版本库的状况:

a. git status就会用config.js的时间戳和长度和index文件里面保存的config.js的时间戳和长度进行比较。

b. 如果相同,则认为没有改变。

c. 如果发现不同。git status会继续用config.js的文件现在的内容和旧版本的config.js(保存在.git/objects中)的内容进行比较。

d. 如果内容没有改变,就简单的将最新的config.js的时间戳信息更新到index文件中

e. 如果内容改变,则提示内容发生改变。但是并不更新index文件中的config.js的时间戳信息。

由于算法优先比较时间戳和长度,避免了当时间戳相同时的文件内容的比较,因此性能比较高。


因此,git add命令会做两件事情:

a.添加文件到暂存区(.git/objects)

b.添加文件索引到(.git/index)3.当git commit被成功执行后,会产生一系列对象表示该commit的结果,都存储在.git/objects目录下。主要分成三部分:

a.tree对象表示当前commit时候的暂存区的目录树,tree对象的内容来自于.git/index文件。

b.blob对象

tree对象目录树中的文件总是以blob的对象被保存。如果tree中有三个文件,那么就有对应的三个blob对象,它们都能通过tree对象保存的这些blob对象的摘要信息(id,文件名,类型等)找到

c.commit对象

该对象记录了属于哪个tree对象,上一次commit的对象id,自己的id,作者等等。

因此,当git commit操作执行的时候,会:

a. 用.git/index文件保存的目录树创建tree对象,

b. 因此tree对象里面自然就指向了已经被git add添加到.git/objects中的blob文件。

c. .git/refs/heads/master文件保存了这次commit的id

4.HEAD文件保存了当前的branch,比如我的HEAD文件内容:

[plain] view plain copy print?

  1. chenshu@sloop2:~/work/189/appengine/.git$ cat HEAD   

  2. ref: refs/heads/master  

也就是说HEAD指向了master分支,如果存在多个分支,HEAD也可指向别的分支。

5. .git/refs 目录称为引用目录

引用就是一个文件,里面包含了一个commit id。.git/refs保存了所有的引用。

.git/refs/heads目录下保存的是分支引用,比如./git/refs/heads/master文件就是master分支的引用。

.git/refs/tags目录保存了tag引用。



本文出自 “小止” 博客,请务必保留此出处http://10541556.blog.51cto.com/10531556/1790431

什么是Git?内部剖析

标签:git

原文地址:http://10541556.blog.51cto.com/10531556/1790431

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!