zoukankan      html  css  js  c++  java
  • GIT对象模型

    GIT对象模型

    <h4>1.SHA </h4>

    所有用来表示项目历史信息的文件,是通过一个40个字符的(40-digit)“对象名”来索引的,对象名看起来像这样:

    <pre lang="bash" escaped="true">6ff87c4664981e4397625791c8ea3bbb5f2279a3</pre>
    你会在Git里到处看到这种“40个字符”字符串。每一个“对象名”都是对“对象”内容做SHA1哈希计算得来的,(SHA1是一种密码学的哈希算法)。这样就意味着两个不同内容的对象不可能有相同的“对象名”。

    这样做会有几个好处:
    <ol>
    <li>Git只要比较对象名,就可以很快的判断两个对象是否相同。</li>
    <li>因为在每个仓库(repository)的“对象名”的计算方法都完全一样,如果同样的内容存在两个不同的仓库中,就会存在相同的“对象名”下。</li>
    <li>Git还可以通过检查对象内容的SHA1的哈希值和“对象名”是否相同,来判断对象内容是否正确。</li>
    </ol>

    <h4>2.对象</h4>

    每个对象(object) 包括三个部分:类型,大小和内容。
    <ol>
    <li>大小就是指内容的大小,</li>
    <li>内容取决于对象的类型,</li>
    <li>有四种类型的对象:"blob"、"tree"、 "commit" 和"tag"。</li>
    </ol>
    四种对象的含义:
    <ul>
    <li>“blob”用来存储文件数据,通常是一个文件。</li>
    <li>“tree”有点像一个目录,它管理一些“tree”或是 “blob”(就像文件和子目录)</li>
    <li>一个“commit”只指向一个"tree",是一个char *const ptr;指针。它用来标记项目某一个特定时间点的状态。它包括一些关于时间点的元数据,如时间戳、最近一次提交的作者、指向上次提交(commits)的指针等等。</li>
    <li>一个“tag”是来标记某一个提交(commit) 的方法。也是一个指针,不能变的指针</li>
    </ul>
    几乎所有的Git功能都是使用这四个简单的对象类型来完成的。它就像是在你本机的文件系统之上构建一个小的文件系统。

    <h4>3.与SVN的区别:</h4>
    Git与你熟悉的大部分版本控制系统的差别是很大的。也许你熟悉Subversion、CVS、Perforce、Mercurial 等等,他们使用 “增量文件系统” (Delta Storage systems), 就是说它们存储每次提交(commit)之间的差异。Git正好与之相反,它会把你的每次提交的文件的全部内容(snapshot)都会记录下来。这会是在使用Git时的一个很重要的理念。

    <h4>4.Blob对象</h4>

    一个blob通常用来存储文件的内容.
    img:


    你可以使用git show命令来查看一个blob对象里的内容。假设我们现在有一个Blob对象的SHA1哈希值,我们可以通过下面的的命令来查看内容:
    <pre lang="c" escaped="true">$ git show 6ff87c4664</pre>
    一个"blob对象"就是一块二进制数据,它没有指向任何东西或有任何其它属性,甚至连文件名都没有.

    因为blob对象内容全部都是数据,如两个文件在一个目录树(或是一个版本仓库)中有同样的数据内容,那么它们将会共享同一个blob对象。Blob对象和其所对应的文件所在路径、文件名是否改被更改都完全没有关系。

    <h4>5.Tree 对象</h4>

    一个tree对象有一串(bunch)指向blob对象或是其它tree对象的指针,它一般用来表示内容之间的目录层次关系。

    git show命令还可以用来查看tree对象,但是git ls-tree能让你看到更多的细节。如果我们有一个tree对象的SHA1哈希值,我们可以像下面一样来查看它:
    <pre lang="bash" escaped="true>
    $ git ls-tree fb3a8bdd0ce
    100644 blob 63c918c667fa005ff12ad89437f2fdc80926e21c .gitignore
    100644 blob 5529b198e8d14decbe4ad99db3f7fb632de0439d .mailmap
    100644 blob 6ff87c4664981e4397625791c8ea3bbb5f2279a3 COPYING
    040000 tree 2fb783e477100ce076f6bf57e4a6f026013dc745 Documentation
    100755 blob 3c0032cec592a765692234f1cba47dfdcc3a9200 GIT-VERSION-GEN
    100644 blob 289b046a443c0647624607d471289b2c7dcd470b INSTALL
    100644 blob 4eb463797adc693dc168b926b6932ff53f17d0b1 Makefile
    100644 blob 548142c327a6790ff8821d67c2ee1eff7a656b52 README
    ...

    </pre>

    就如同你所见,一个tree对象包括一串(list)条目,每一个条目包括:mode、对象类型、SHA1值 和名字(这串条目是按名字排序的)。它用来表示一个目录树的内容。

    一个tree对象可以指向(reference): 一个包含文件内容的blob对象, 也可以是其它包含某个子目录内容的其它tree对象. Tree对象、blob对象和其它所有的对象一样,都用其内容的SHA1哈希值来命名的;只有当两个tree对象的内容完全相同(包括其所指向所有子对象)时,它的名字才会一样,反之亦然。这样就能让Git仅仅通过比较两个相关的tree对象的名字是否相同,来快速的判断其内容是否不同。

    (注意:在submodules里,trees对象也可以指向commits对象. 请参见 Submodules 章节)

    注意:所有的文件的mode位都是644 或 755,这意味着Git只关心文件的可执行位.

    <h4>6.Commit对象</h4>

    "commit对象"指向一个"tree对象", 并且带有相关的描述信息.

    img:

    你可以用 --pretty=raw 参数来配合 git show 或 git log 去查看某个提交(commit):
    <pre lang="bash" escaped="true">

    $ git show -s --pretty=raw 2be7fcb476
    commit 2be7fcb4764f2dbcee52635b91fedb1b3dcf7ab4
    tree fb3a8bdd0ceddd019615af4d57a53f43d8cee2bf
    parent 257a84d9d02e90447b149af58b271c19405edb6a
    author Dave Watson <dwatson@mimvista.com> 1187576872 -0400
    committer Junio C Hamano <gitster@pobox.com> 1187591163 -0700

    Fix misspelling of 'suppress' in docs

    Signed-off-by: Junio C Hamano <gitster@pobox.com>

    </pre>

    你可以看到, 一个提交(commit)由以下的部分组成:

    一个 tree 对象: tree对象的SHA1签名, 代表着目录在某一时间点的内容.

    父对象 (parent(s)): 提交(commit)的SHA1签名代表着当前提交前一步的项目历史. 上面的那个例子就只有一个父对象; 合并的提交(merge commits)可能会有不只一个父对象. 如果一个提交没有父对象, 那么我们就叫它“根提交"(root commit), 它就代表着项目最初的一个版本(revision). 每个项目必须有至少有一个“根提交"(root commit). 一个项目可能有多个"根提交“,虽然这并不常见(这不是好的作法).

    作者 : 做了此次修改的人的名字, 还有修改日期.

    提交者(committer): 实际创建提交(commit)的人的名字, 同时也带有提交日期. TA可能会和作者不是同一个人; 例如作者写一个补丁(patch)并把它用邮件发给提交者, 由他来创建提交(commit).

    -注释 用来描述此次提交.

    注意: 一个提交(commit)本身并没有包括任何信息来说明其做了哪些修改; 所有的修改(changes)都是通过与父提交(parents)的内容比较而得出的. 值得一提的是, 尽管git可以检测到文件内容不变而路径改变的情况, 但是它不会去显式(explicitly)的记录文件的更名操作. (你可以看一下 git diff 的 -M 参数的用法)

    一般用 git commit 来创建一个提交(commit), 这个提交(commit)的父对象一般是当前分支(current HEAD), 同时把存储在当前索引(index)的内容全部提交.

  • 相关阅读:
    how to pass a Javabean to server In Model2 architecture.
    What is the Web Appliation Archive, abbreviation is "WAR"
    Understaning Javascript OO
    Genetic Fraud
    poj 3211 Washing Clothes
    poj 2385 Apple Catching
    Magic Star
    关于memset的用法几点
    c++ 函数
    zoj 2972 Hurdles of 110m
  • 原文地址:https://www.cnblogs.com/liweilijie/p/4984061.html
Copyright © 2011-2022 走看看