【Git】Git指令学习与其原理探究(一)

这篇文章记录我学习Git的过程中遇到的问题及对于某些问题的看法,如有错误,还望不吝赐教!

ps:这篇文章介绍本地库,下篇将介绍与远程库的交互。

Git是什么 & 为什么要有Git?

既然您能看到这篇文章,相信你对Git也有了一点点的了解,或者您本来就是大神,来观望下博主而已。

言归正传,那么到底什么是Git呢!

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

Git有什么特点?简单来说就是:高端大气上档次!

那么什么是版本控制系统呢?:所谓的版本控制系统呢,简单来说就是你写的一个小项目,经过多次修改,你发现这和你原本的意愿越走越远,此时就想退回原来未修改前版本代码,但是你发现这可不是一件简单的事,然后你想有没有一种工具能让我在写的各个版本的源代码之间随意切换,满足我的要求,那岂不是太爽了。这个需求linus帮你完成了,没错还是这个人。两周时间自己用C写了一个分布式版本控制系统,这就是Git!一个月之内,Linux系统的源码已经由Git管理了!牛是怎么定义的呢?大家可以体会一下。

Git迅速成为最流行的分布式版本控制系统,尤其是2008年,GitHub网站上线了,它为开源项目免费提供Git存储,无数开源项目开始迁移至GitHub,包括jQuery,PHP,Ruby等等。

SVN与Git的最主要的区别?

SVN也是一种版本控制系统,不过它是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以首先要从中央服务器哪里得到最新的版本,然后干活,干完后,需要把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作,如果在局域网还可以,带宽够大,速度够快,如果在互联网下,如果网速慢的话,就纳闷了。

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

Git是如何工作的?

首先看张图吧

图中是我们经常使用的几个命令,接下来我将根据图中的命令详细介绍各个部分。远程仓库,本地仓库,工作区和暂存区的功能以及他们如何协调工作的。

Git本地仓库:

git的本地仓库主要有两部分:

工作区(WorkSpace)就是存放你实际文件的地方,主要保存些你的代码,文件夹等,你在这个目录下操作自己的文件,这些文件都是最后你要上传到远程仓库的。

版本库(.git): 这个文件夹是你自己创建的目录,具体操作请自行百度。版本库又名仓库,英文名repository,你可以简单的理解一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改,删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻还可以将文件”还原”,满足你的需求。当我们通过git
init命令将一个目录编程git可以管理的仓库时,这个目录下就会生成一个隐藏的.git文件夹,这就是git的根本,git就是通过这个文件夹来完成我们的指令操作。.git目录下还存在好多目录,下面我们将介绍下上图中的几个比较重要的目录,有的是文件。

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

.git/objects目录下的对象都有一个40位的id,前两位作为目录名,后38位作为文件名,您可以自行查看下,这些对象主要是commit对象和tree对象(目录树)。

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指向了master分支,如果存在多个分支,HEAD也可指向别的分支。

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

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

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

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

下面介绍一下上面所说的三个属于git的对象,它们的组成如图所示

如上是三个git的对象,那么他们是如何组织的呢,如下图:

下面我们将更具一次具体的操作来分析一下,常用指令的工作原理。

还是先上图:

当我们通过git add命令将文件添加到暂且区的时候,git add会做两件事

1,添加文件到暂存区(.git/objects),保存实际文件的内容(修改后)

2,index保存文件索引。

然后git commit将暂存区的文件提交时会存在上面说过的情况,

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

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

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

这就是add,commit命令的工作原理。上述c选项保存的id就是提供以后返回某个版本的根据。

下面我们学习常用的命令:

git add 用于提交文件从working directory到index area

git commit用于提交文件从stage area到history(版本库)

git commit -a用于提交文件直接从working directory到history

git reset用于撤销文件与git commit过程相反

git checkout用于撤销文件与git add过程相反

git status:可以列出当前目录所有还没有被git管理的文件和被git管理且被修改但还未提交(git commit)的文件。

git diff命令:

git diff用于区别某一文件在working directory与stage area的区别

git diff --cached用于区别某一文件在stage area与history的区别

git diff HEAD用于区别某一文件在working directory与history的区别

git log命令显示从最近到最远的显示日志。

git reset  –hard HEAD^返回上个版本。

git reflog 获得版本号。

git reset  –hard 版本号 :会退到此版本之后的版本。

git checkout  — file 可以丢弃工作区的修改。

git commit -m "代码提交信息"

命令 git checkout –readme.txt 意思就是,把readme.txt文件在工作区做的修改全部撤销,这里有2种情况,如下:

    1. readme.txt自动修改后,还没有放到暂存区,使用 撤销修改就回到和版本库一模一样的状态。
    2. 另外一种是readme.txt已经放入暂存区了,接着又作了修改,撤销修改就回到添加暂存区后的状态。

对于第二种情况,我想我们继续做demo来看下,假如现在我对readme.txt添加一行 内容为6666666666666,我git add 增加到暂存区    后,接着添加内容7777777,我想通过撤销命令让其回到暂存区后的状态。如下所示:

到此,本地库的探究就结束了,博主也是根据网上资料分析得出的这些点,难免有错误,还望指出,另外对于有的问题,涉入到git的原理,如若深剖,则也不是一两句就能说清的,有兴趣的读者可以参考下分享的资料,自行研究。

参考资料:

Git 内部原理 - Git 对象:https://git-scm.com/book/zh/v1/Git-%E5%86%85%E9%83%A8%E5%8E%9F%E7%90%86-Git-%E5%AF%B9%E8%B1%A1

git本地仓库内部结构:http://blog.csdn.net/csfreebird/article/details/7925281

廖雪峰git教程:http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000

git零基础深入浅出:http://blog.csdn.net/irean_lau/article/details/51661572#comments

手把手教你使用git:http://blog.jobbole.com/78960/

时间: 2024-10-06 04:04:16

【Git】Git指令学习与其原理探究(一)的相关文章

git常用指令整理及说明(详细)

git常用指令整理及说明(详细) git常用指令整理及说明详细 安装和配置 工作区版本库和暂存区 本地库和远程库 新建仓库 从远程库克隆 常用查看指令 常用修改指令 撤销修改和版本回退 分支管理 创建和合并分支 解决冲突 bug分支 远程分支 优秀教程笔记 本文是git系列博客的第二篇.本文对指令按照使用场景(建库,查看,修改,分支)进行分类归纳,介绍指令基本含义和用法,方便查阅. 安装和配置 参考我前面的博客:git在各操作系统平台下的安装和配置 工作区.版本库和暂存区 工作区:就是你在电脑里

源代码管理——git(分布式版本控制和集中式版本控制对比,git和SVN对比,git常用指令,搭建GitHub远程仓库,搭建oschina远程仓库 )

一.git简介 什么是git? git是一款开源的分布式版本控制工具 在世界上所有的分布式版本控制工具中,git是最快.最简单.最流行的 git的起源 作者是Linux之父:Linus Benedict Torvalds 当初开发git仅仅是为了辅助Linux内核的开发(管理源代码) git的现状 在国外已经非常普及,国内并未普及(在慢慢普及) 越来越多的开源项目已经转移到git CVS 最早的开源.免费的集中式版本控制工具 自身设计有问题,会造成提交文件不完整,版本库莫名其妙损坏的情况 SVN

Git操作指令进阶

注意: 学习前请先配置好Git客户端 相关文章:Git客户端图文详解如何安装配置GitHub操作流程攻略 官方中文手册:http://git-scm.com/book/zh GIT 学习手册简介 本站为 Git 学习参考手册.目的是为学习与记忆 Git 使用中最重要.最普遍的命令提供快速翻阅. 这些命令以你可能需要的操作类型划分,并且将提供日常使用中需要的一些常用的命令以及参数. 本手册将从入门到精通指导大家. 首先,我们要从如何以 Git 的思维方式管理源代码开始. 如何以 GIT 的方式思考

Git版本控制工具学习

Git代码管理工具学习 分布式管理工具:git 相比较svn它更加的方便,基本上我们的操作都是在本地进行的. Git文件的三种状态:已提交,已修改,以暂存. 已提交:表示文件已经被保存到本地数据库. 已修改:修改了某个文件. 以暂存:把修改的文件放到了下次提交保存的清单中. Git只关心文件系统的整体是否发生了变化,其它的版本控制工具更多的关心文件的内容是否发生变化. Git基本的工作流程 1:在工作目录中修改某些文件,2:对修改后的文件进行快照,然后保存到暂存区域.3:提交更新,将保存在暂存区

Git实战(二)原理

上次的博文Git实战(一)版本号控制概述中我们简介了一下版本号控制系统的概念,重点对版本号控制的三种类型进行了分析和对照,从本篇博文開始我们进入Git的世界,首先介绍一下Git实现版本号控制的原理. Git与SVN等其它版本号控制系统的最重要的一点差别在于,Git仅仅关心文件数据的总体是否变化,而不是关心文件内容的差异. SVN等原理分析        怎样理解呢?我们能够通过两种图进行比較,首先看一下SVN等其它版本号控制系统的原理图,例如以下所看到的: 在上述图片中,横向表示各个版本号,纵向

Git权威指南学习笔记(一)Git初始化

1.在Git中配置用户名和邮件地址 $ git config --global user.name "Jymn_Chen" $ git config --global user.email "[email protected]" 注意把用户名和邮件地址替换成你自己的资料. 在这里的参数global表示配置的作用范围是当前用户,如果将参数改为system,那么配置的作用范围是系统中的所有用户. 2.创建版本库 新建一个目录并cd到目录中,执行以下命令: $ git i

Git权威指南学习笔记(二)Git暂存区

如下图所示: 左侧为工作区,是我们的工作目录. 右侧为版本库,其中: index标记的是暂存区(stage),所处目录为.git/index,记录了文件的状态和变更信息. master标记的是master分支所代表的目录树.HEAD指向master分支. objects标记的是Git的对象库,所处目录为.git/objects,文件索引建立了文件和对象库中对象实体之间的映射关系. 通过该图我们可以清晰地看出add,commit等命令的转化关系.下面通过git diff和git status两条命

Git之初步学习

我的GitHub地址是:https://github.com/hbuxiaopipi     Git的初步学习首先让我明白了一个道理:学好英语非常关键.浏览英文网页和使用英文软件对于我这种英语渣渣来讲真是难于登天,但最终我还是借助各种翻译软件和翻译平台再加上我的所谓的英语的语感像学习文言文一样理解了大概的意思.由于对Git是一窍不懂,刚开始个学习的过程也是一脸懵逼.幸亏有肖老师提供的几个Git的教程链接,终于在看了n遍教程和按照教程尝试了x遍以后有所顿悟,但不得不说我现在还是处于半懵逼状态,Gi

Git常用指令总结

git 已经成为日常开发流不可或缺的一部分,甚至说是核心部分,但有些不常用指令时常会忘记,再次坐下备忘,省的用到的时候再去找了.用到的时候才会记录,指令是不断增加的,请不要见怪 ~>~ git 常用指令总结 command 说明 备注 git pull 从远程拉去代码到本地,并自动合并 merge Text git push git fetch 从远程拉取代码到本地,不自动合并 可能会有缓存问题 git fetch -p 从远程拉取代码到本地,不自动合并 可以解决缓存问题 git branch