Git對象
在Git系統(tǒng)中有四種類型的對象减江,幾乎所有Git操作都是在這四種Git對象上進行的染突,所以了解這四種對象的作用對于應用Git有很大幫助。這四種對象是:
- “blob”:一個“blob”通常用來存儲文件的內(nèi)容辈灼。一個“blob”對象就是一塊二進制數(shù)據(jù)份企,它沒有指向任何東西或有任何其它屬性,甚至沒有文件名巡莹。因為“blob”對象內(nèi)容全部都是數(shù)據(jù)司志,所以如若兩個文件在一個目錄樹或是一個版本倉庫中有同樣的數(shù)據(jù)內(nèi)容,那么它們將會共享同一個“blob”對象降宅÷钤叮“blob”對象和其所對應的文件所在路徑、文件名是否改被更改都完全沒有關(guān)系腰根。
- “tree”:像一個目錄激才,管理一些“tree”對象或是“blob”對象。它有一串指向“blob”對象或是其它“tree”對象的指針额嘿,一般用來表示內(nèi)容之間的目錄層次關(guān)系(就像文件和子目錄)瘸恼。
- “commit”:“commit”對象指向一個“tree對象”,并且?guī)в邢嚓P(guān)的描述信息册养,標記項目某一個特定時間點的狀態(tài)东帅。它包括一些關(guān)于時間點的元數(shù)據(jù),如時間戳捕儒、最近一次提交的作者冰啃、指向上次提交的指針等等邓夕。
- “tag”:一個“tag”對象包括一個對象名(SHA1簽名)刘莹、對象類型、標簽名焚刚、標簽創(chuàng)建人的名字(“tagger”), 還有一條可能包含有簽名(signature)的消息点弯。
例如我們有一個項目,如果我們把它提交(commit)到一個Git倉庫中, 在Git中“blob”矿咕、“commit”和“tree”對象的關(guān)系看起來會如下圖:
可以看到: 每個目錄都創(chuàng)建了“tree”對象, 每個文件都創(chuàng)建了一個對應的“blob”對象抢肛。最后有一個“commit”對象來指向根“tree”對象,這樣我們就可以追蹤項目每一項提交內(nèi)容碳柱。
SHA1哈希值
另外在Git里隨處可見一種“40個字符”的字符串捡絮。由于Git中每一個“對象名”都是對“對象”內(nèi)容做SHA1(SHA1是一種密碼學的哈希算法)哈希計算得來的,所以對于內(nèi)容不同的對象莲镣,會有不同的SHA1哈希值福稳。這樣就意味著兩個不同內(nèi)容的對象不可能有相同的“對象名”。
例如 6ff87c4664981e4397625791c8ea3bbb5f2279a3
這樣做的好處是:
- Git只要比較對象名瑞侮,就可以很快的判斷兩個對象是否相同的圆,而且通過檢查對象內(nèi)容的SHA1的哈希值和“對象名”是否相同鼓拧,還可以來判斷對象內(nèi)容是否正確。
- 因為在每個repository的“對象名”的計算方法都完全一樣越妈,所以同樣的內(nèi)容存在兩個不同的倉庫中季俩,都會存在相同的“對象名”下。
查看對象
- 查看“blob”對象:git show + 對象名(SHA1哈希值)
- 查看“tree”對象:git show + 對象名 / git ls-tree + 對象名
- 查看“commit”對象:git show / git log + -s + --pretty=raw +對象名
- 查看“tag”對象:git cat-file tag v1.5.0
著重說一下“tree”和“commit”對象
- “tree”:
$ 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
如上:一個tree對象包括一串條目梅掠,每一個條目包括:mode(mode位都是644 或 755酌住,這意味著Git只關(guān)心文件的可執(zhí)行位.)、對象類型瓤檐、對象名和文件名字赂韵。它用來表示一個目錄樹的內(nèi)容。
一個tree對象可以指向一個包含文件內(nèi)容的blob對象挠蛉,也可以是包含某個子目錄內(nèi)容的其它tree對象祭示。“tree”對象谴古、“blob”對象和其它所有的對象一樣质涛,都用其內(nèi)容的SHA1哈希值來命名的;只有當兩個tree對象的內(nèi)容完全相同(包括其所指向所有子對象)時掰担,它的名字才會一樣汇陆,反之亦然。這樣就能讓Git僅僅通過比較兩個相關(guān)的tree對象的名字是否相同带饱,來快速的判斷其內(nèi)容是否不同毡代。在有些情況下,“tree”對象也可以指向“commit”對象勺疼。
- “commit”:
$ 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>
可以看到教寂,一個提交(commit)由以下的部分組成:
- 一個“tree”對象:“tree”對象的SHA1簽名,代表著目錄在某一時間點的內(nèi)容执庐。
- 父對象(parent(s)):提交的SHA1簽名代表著當前提交前一步的項目歷史酪耕。上面的那個例子就只有一個父對象;合并的提交(merge commits)可能會有不只一個父對象轨淌。如果一個提交沒有父對象迂烁,那么我們就叫它“根提交”(root commit),它就代表著項目最初的一個版本(revision)递鹉。每個項目必須有至少有一個“根提交”(root commit)盟步。一個項目可能有多個“根提交”,雖然這并不常見躏结。
- 作者:做了此次修改的人的名字却盘,還有修改日期。
- 提交者(committer):實際創(chuàng)建提交(commit)的人的名字,同時也帶有提交日期谷炸”弊ǎ可能會和作者不是同一個人;例如作者寫一個補丁(patch)并把它用郵件發(fā)給提交者, 由他來創(chuàng)建提交(commit)旬陡。
- 注釋:用來描述此次提交.
一個提交本身并沒有包括任何信息來說明其做了哪些修改拓颓;所有的修改(changes)都是通過與父提交(parents)的內(nèi)容比較而得出的。盡管git可以檢測到文件內(nèi)容不變而路徑改變的情況描孟,但是它不會去顯式(explicitly)記錄文件的更名操作驶睦。
一般用git commit
來創(chuàng)建一個提交(commit), 這個提交的父對象一般是當前分支(current HEAD),同時把存儲在當前索引(index)的內(nèi)容全部提交匿醒。