git plumbing 更加底层命令解析-深入理解GIT

原文: http://rypress.com/tutorials/git/plumbing

本文详细介绍GIT Plumbing--更加底层的git命令,你将会对git在内部是如何管理和呈现一个项目repo有一个深入的理解。

除非你想通读Git源代码,你可能永远没有必要使用下面的命令。但是通过手工的操作一个repo将会让你对于GIT如何保存数据的概念细节有个深入理解,你也将对于git是如何工作的有更好的理解。

我们首先来检阅Git的object database,然后我们使用git的低级命令手工创建和commit一个snapshot

Examine Commit Details

首先我们通过git cat-file plumbing command来查看最近的一个commit:

git cat-file commit HEAD

commit参数告诉git我们需要查看一个commit对象。正如我们所知,HEAD指向最近的commit.这将输出下面的信息:

tree 552acd444696ccb1c3afe68a55ae8b20ece2b0e6
parent 6a1d380780a83ef5f49523777c5e8d801b7b9ba2
author Ryan <[email protected]> 1326496982 -0600
committer Ryan <[email protected]> 1326496982 -0600

Add .gitignore file

这是代表一个commit的完整信息:一个tree,一个parent,用户数据和一个commit message.用户信息和commit消息是非常容易理解的,但我们从来没有见过tree或者parent.

一个tree object是git对于一个"snapshot"的代表。他们保存了一个目录在特定时刻的状态,该object没有任何关于时间或者作者的信息。为了将tree和项目一贯的历史信息关联起来,GIT将每一个tree对象包装在一个commit对象中,并且指定一个parent,而这个parent实际上就是另外一个commit.通过遍历每一个commit的parent,你就可以遍历完项目的整个历史。

注意每一个commit refers to one and only one tree object,也就是说commit和tree是一一对应的。从git cat-file输出的内容看,我们可以使用SHA checksum来代表那个tree.这个SHA CHECKSUM对于GIT内部每一个变量都是适用的。

Examine a Tree

下面我们使用git cat-file命令来检阅一个TREE对象。注意将相关的id更新为你的tree的id:

git cat-file tree 552acd4

不幸的是上述命令输出的是binary数据,无法阅读。你可以通过使用下面的git ls-tree命令来输出可阅读的内容。

git ls-tree 552acd4

该命令将输出目录的列表:

100644 blob 99ed0d431c5a19f147da3c4cb8421b5566600449    .gitignore
040000 tree ab4947cb27ef8731f7a54660655afaedaf45444d    about
100644 blob cefb5a651557e135666af4c07c7f2ab4b8124bd7    blue.html
100644 blob cb01ae23932fd9704fdc5e077bc3c1184e1af6b9    green.html
100644 blob e993e5fa85a436b2bb05b6a8018e81f8e8864a24    index.html
100644 blob 2a6deedee35cc59a83b1d978b0b8b7963e8298e9    news-1.html
100644 blob 0171687fc1b23aa56c24c54168cdebaefecf7d71    news-2.html
...

通过检查上面命令的输出内容,我们可以假定"blobs"代表了我们repo里面的文件,而trees代表了repo里面的folders。继续通过git ls-tree检阅about tree,我们就可以看到是不是我们的假定是正确的了。

所以,blob对象实际上就是git保存我们文件内容的对象,可以简单理解为文件,tree对象组合了blob和其他的tree对象形成了目录列表,也就是说tree可以简单理解为目录。这些对象就是git最终形成我们在git中常用命令所操作的唯一对象。commit,tree,blob之间的关系可以用下面的图形象展示:

Examine a Blob

我们来看看和blue.html文件相对应的blob:

git cat-file blob cefb5a6

这会展示blue.html文件的整个内容,这也印证了blob本身就是存数据文件,blob本身是纯粹的content,它本身甚至没有任何关于文件名称的信息。也就是说文件名blue.html是保存在包含blob的tree对象中,而不是在blob对象中。

你可能知道SHA-1 checksum确保一个对象的内容永远不会在Git不知情的情况下被篡改。checksum的原理是通过使用对象内容来计算一个唯一的字符序列。这不仅作为一个id,而且它保证一个对象永远不会悄无声息地被修改(而git竟然不知情).当我们来谈到blob对象时,这又有另外一个好处。既然两个具有相同内容的blob永远具有相同的checksum id,那么git可以跨tree来共享一个blob对象。比如我们的blue.html文件自从被创建后就没有被修改,那么我们的repo将只有一个相关联的blob,而所有后续的tree对象都将引用它。通过不去创建重复的blob,Git可以大大降低repo的尺寸。有这个理念作为基础,我们可以修正git的对象图如下:

然而,只要你更改文件的任何一行,Git都必需创建一个新的blob对象来反映这个修改,因为内容变更,SHA-1 checksum就将变更。当然,GIT也有一些增量修改的机制来保证这个尺寸增加不是很大的问题。

Examine a Tag

第四个也是最后一个git object是tag对象

时间: 2024-10-08 11:17:42

git plumbing 更加底层命令解析-深入理解GIT的相关文章

使用plumbing命令来深入理解git add和git commit的工作原理

前言: plumbing命令 和 porcelain命令 git中的命令分为plumbing命令和porcelain命令: porcelain命令就是我们常用的git add,git commit等命令 plumbing命令可以理解为更底层的命令,实际上一个porcelain命令可以由若干个plumbing命令完成(见下文),plumbing命令可以帮助我们了解git底层的工作原理 阅读本文还需要了解.git目录的结构功能,以及git中的对象(commit对象.tree对象.blob对象等等)等

理解git常用命令原理

git不同于类似SVN这种版本管理系统,虽然熟悉常用的操作就可以满足大部分需求,但为了在遇到麻烦时不至于靠蛮力去尝试,了解git的原理还是很有必要. 文件 通过git管理的文件版本信息全部存放在根目录.git下,稍微看下: $ ls .git COMMIT_EDITMSG HEAD branches description index logs packed-refs FETCH_HEAD ORIG_HEAD config hooks info objects refs git除了提供给我们平时

【Git 学习】深入理解git reset 命令

重置命令(git reset)是Git 最常用的命令之一,也是最危险最容易误用的命令.来看看git reset命令用法. ----------------------------------------------------------------------------------------------------------- 用法一:git reset [-q]  [<commit>] [--] <paths>..... 用法二:git reset [--soft | -

git status -s命令解析

git status -s 以精简的方式显示文件状态. git status 输出的命令很详细,但有些繁琐. 如果用 git status -s 或 git status --short 命令,会得到更为紧凑的格式输出. 新添加的未跟踪文件前面有 ?? 标记, 新添加到暂存区中的文件前面有 A 标记, 修改过的文件前面有 M标记. M 有两个可以出现的位置,出现在右边的 M 表示该文件被修改了但是还没放入暂存区,出现在靠左边的 M 表示该文件被修改了并放入了暂存区. 输出标记会有两列,第一列是对

理解git

为了真正了解git,我们从底部.底层开始,了解git核心,知其然并知其所以然. 为什么要进行版本控制呢? 因为编写文件不可能一次到位,文件总是有不同的状态需要保存下来,方便以后出错回滚. git 是目前最先进的版本控制软件(VCS,version control system),它是linux之父Linus Torvalds的第二个作品. 正如git所命名的那样,是“愚蠢或不开心的人”,Linus评价“git is a British English slang for a stupid or

彻底理解Git

Translated from http://maryrosecook.com/blog/post/git-from-the-inside-out. 本文原地址:https://github.com/pysnow530/git-from-the-inside-out/blob/master/README.md 彻底理解Git 本文主要解释git的工作原理.如果你是一个视频党,请移步youtube视频. 本文假设你已经了解Git,并可以使用它来对项目做版本控制.我们主要考察支撑Git的图结构和指导

使用git微命令深入理解git工作机制

首先,这篇不是真正意义上的翻译,所以大家在看的时候不要找对应的英文文章对应着看.这篇文章之所以归类为翻译,是因为最开始有一篇英文文章让我对git内部机制有了清楚的认识,它可以说是我git的启蒙老师吧.然后很久过去后,自己也有了很多的git项目实践,觉得有必要从自己的理解角度(微命令和常用命令对应分析)来整理下自己的理解,于是有了这篇博文. git是一种管理数据的工具,一种支持快速索引查找数据并管理数据变化的工具.它为数据添加一个头封装为对象块(本文称为git对象)然后保存为文件,并根据数据生成一

Git中的merge命令实现和工作方式

想象一下有如下情形:代码库中存在两个分支,并且每个分支都进行了修改,最后你想要将其中的一个分支合并到其他的分支中.个人博客网址 http://swinghu.github.com/ 那么要问合并的处理过程是怎么样的呢?Git是对每个分支,依据分支的历史数据按照序列化操作,还是它只是合并每个分支里文件的最后版本?这是一个问题,我想对git的merge操作有必要进行分析一下. 回忆一下,我们知道Git的版本库内部结构是以有向无环图(directed acyclic graph)组织起来的:每一次co

git常用的一些命令总结

git常用的一些命令总结 git init 创建一个版本库 git add file 将文件从工作区提交到暂存区 git commit -m "blabla--" 将文件中暂存区提交到仓库 git status 查看仓库当前的状态 git diff 可以查看具体修改了哪些内容 git log 查看我们提交的历史记录 git log –pretty=oneline #输出少量版本信息和提交的内容 git reset –hard HEAD^ #返回上一个版本 cat filename #查