Git版本控制管理學習筆記3-基本的Git概念

爲了更近一步的學習和理解Git的理念,這一節介紹一下Git中的一些基本概念。git

  • 基本概念
  • 對象庫圖示
  • Git在工做時的概念

1、基本概念:

一、版本庫:

    Git的版本庫就是一個簡單的數據庫,其中包含全部用來維護和管理項目的修訂版本和歷史的信息。數據庫

    Git不只提供版本庫中全部文件的副本,還提供了版本庫自己的副本。數據結構

    Git在每一個版本庫裏維護一組配置值,這個咱們在上一篇文章中已經有所說起,好比版本庫的用戶名和email地址。當把一個版本庫進行克隆的時候,會複製文件數據以及其餘的一些版本庫的元數據,可是不會複製配置設置學習

    Git維護兩個主要的數據結構:對象庫和索引。全部這些數據都存放在.git隱藏目錄內。測試

二、Git對象類型:

    對象庫包含原始數據文件、全部的日誌消息、做者信息、日期、以及其餘用來重建項目任意版本或分支的信息。spa

    Git放在對象庫裏的對象只有4種類型:塊(blob)、目錄樹(tree)、提交(commit)、標籤(tag)3d

    A、塊:日誌

         文件的每個版本被表示爲一個blob。一個blob保存一個文件的數據,但不包含任何關於這個文件的元數據,甚至文件名。code

    B、目錄樹(tree):對象

        一個目錄樹對象表明一層目錄信息。它記錄了blob標識符、路徑名和在一個目錄裏全部文件的一些元數據。

    C、提交(commit):

        一個提交對象保存版本庫中每一次變化的元數據:做者、提交者、提交日期、日誌消息。每個提交對象指向一個目錄樹對象,除了根提交,大多數提交都有一個父提交。

    D、標籤(tag):一個標籤對象分配一個任意的可讀的名字給一個特定對象(一般是一個提交對象)。

三、索引:

    目前來講,感受這個概念不太好解釋。

    索引是一個臨時的、動態的二進制文件,它描述整個版本庫的目錄結構。

    個人認識是,索引是介於工做區和對象庫之間的一個緩衝區。工做區裏的變化會最先在這裏有所體現,最後由索引將全部的變更提交到對象庫中。

四、可尋址內容名稱:

    Git對象庫被組織及實現爲一個內容尋址的存儲系統。對象庫中的每個對象都有一個惟一的名稱,這個名稱是向對象的內容應用SHA1獲得的散列值。

五、Git追蹤內容:

    首先,Git追蹤的是基於對象內容計算出的散列值,而不關心文件名或目錄名。若是兩個文件的內容相同,那麼無論是否在一樣的目錄,Git在對象庫中只保存一份blob形式的內容副本。

    其次,當文件從一個版本變到下一個版本的時候,Git的內部數據庫會有效的存儲每個文件的每一個版本,而不只僅是差別。

    固然,你或許已經發現,上面說的這種存儲方式效率很低,由於每個都要保存副本。這個會在後面打包文件的地方進行說明。

六、路徑名和內容:

    Git僅僅記錄每一個文件名,而且確保能經過它的內容精確的重建文件和目錄。

    好吧。。。我仍是感受沒法理解做者的意思。

七、打包文件:

    回到上面提出的問題:直接存儲每一個文件每一個版本的完整內容是否過低效了?

    Git使用了一種叫作打包文件的存儲機制。要建立一個打包文件,Git首先定位內容很是類似的所有文件,而後爲它們之一存儲整個內容。以後計算類似文件之間的差別而且只存儲差別。


2、對象庫圖示:

    先來張圖壓壓驚。。。經過這張圖看看對象庫中的各個對象是如何協做造成整個系統的。

image
  • blob對象是數據結構的底端,它什麼也不引用,且只被樹引用。上圖中,每一個blob對象都用一個矩形來表示。
  • 樹對象指向若干個blob對象,也能夠指向其餘樹對象。許多不一樣的提交對象可能指向任何給定的樹對象。
  • 一個圓圈表明一個提交對象,每一個提交對象都要指向一個樹對象,而且這個樹對象是由該提交對象引入到版本庫中的。
  • 每一個標籤最多能夠指向一個提交對象。
  • 分支並非一個基本的Git對象,可是它在命名提交對象的時候有相當重要的做用。

下面咱們讓對象庫變得複雜一些。保留原來的兩個文件不變,添加一個包含一個文件的新目錄到版本庫中。對象圖以下:

image

這裏由於頂級目錄被添加的新子目錄改變了,因此頂級樹對象的內容也就跟着改變了。因此Git引入了一棵新的樹cafed00d。

樹cafed00d依舊引用了原來的兩個文件的blob對象,同時新增了一個指向新子目錄的樹對象。

上面的圖是全部Git操做諸如add,commit等所有結束後的對象庫總體圖,但是咱們可能更想知道如下問題:

  • 新子目錄的樹對象是什麼時候建立的?
  • master分支爲什麼指向了新的提交對象?
  • 新提交的文件對應的blob對象是什麼時候由誰來建立的?

後面的章節會依次說明上述問題。


3、Git在工做時的概念:

一、進入.git目錄:

咱們新建一個新的版本庫,逐步查看一下每次操做後.git目錄中會發生哪些變化:

首先,咱們建立一個空的版本庫。

image

咱們能夠看到,除了幾個佔位符外,.git/objects目錄下是空的:

image

[root@flower1 test]# find .git/objects/
.git/objects/
.git/objects/pack
.git/objects/info

如今,咱們建立一個簡單的文件,並添加到對象庫中。

[root@flower1 test]# echo "hello world" > hello.txt
[root@flower1 test]# git add hello.txt

接下來,咱們看一下objects目錄下發生的變化:

[root@flower1 test]# find .git/objects/
.git/objects/
.git/objects/3b
.git/objects/3b/18e512dba79e4c8300dd08aeb37f8e728b8dad
.git/objects/pack
.git/objects/info

二、對象、散列和blob:

    從上面的例子裏,咱們看到,當爲hello.txt建立一個對象的時候,Git並不關心hello.txt的文件名。Git只關心文件裏的內容。Git對這個blob執行一些操做,計算它的SHA1散列碼,並散列碼的十六進制表示做爲文件名放進對象庫裏。

    其實上述文件的散列碼是3b18e512dba79e4c8300dd08aeb37f8e728b8dad。

    Git將散列碼的前2個字符做爲一級目錄名,能夠提升文件系統的效率,至關於將不一樣對象散列到了不一樣的文件夾下,避免某個文件目錄下文件過多。

    咱們可使用下面命令使用散列碼將文件的內容提出出來:

[root@flower1 test]# git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad
hello world

   固然,手動收入長度爲40的散列碼很不切實際,因此Git提供了下面的方式:經過對象的惟一前綴來查找對象的散列值。

[root@flower1 test]# git rev-parse 3b18
3b18e512dba79e4c8300dd08aeb37f8e728b8dad
[root@flower1 test]# git rev-parse 3b18e
3b18e512dba79e4c8300dd08aeb37f8e728b8dad
[root@flower1 test]# git rev-parse 3b18e5
3b18e512dba79e4c8300dd08aeb37f8e728b8dad
image

我測試的結果是,前綴最少要達到4位才能夠。

三、文件和樹:

經過上面的演示,咱們看到表明hello world的blob對象已經存放到對象庫中了。那麼它的文件名又發生了什麼事呢?

Git經過另外一種叫作目錄樹的對象來跟蹤文件的路徑名。當使用git add命令時,Git會給添加的每一個文件的內容建立一個對象,但不會立刻爲樹建立一個對象。

此時,索引更新了。索引位於.git/index中,它跟蹤文件的路徑名和相應的blob。每次執行命令時,Git會用心的路徑名和blob信息來更新索引。

任什麼時候候,均可以從當前索引建立一個樹對象,只要經過底層的git write-tree命令來捕獲索引當前信息的快照就能夠了。

當前,該索引只包含一個文件:

[root@flower1 test]# git ls-files -s
100644 3b18e512dba79e4c8300dd08aeb37f8e728b8dad 0    hello.txt

從上面的打印信息,能夠看到文件的關聯,hello.txt和3b18e512…的blob。

接下來咱們捕獲索引狀態並把它保存到一個樹對象裏:

[root@flower1 test]# git write-tree
68aba62e560c0ebc3396e8ae9335232cd93a3f60
[root@flower1 test]# find .git/objects/
.git/objects/
.git/objects/3b
.git/objects/3b/18e512dba79e4c8300dd08aeb37f8e728b8dad
.git/objects/68
.git/objects/68/aba62e560c0ebc3396e8ae9335232cd93a3f60
.git/objects/pack
.git/objects/info

如今有2個對象:3b18e5的hello world對象和68aba6的樹對象。

咱們也能夠看看樹對象裏面的內容究竟是什麼:

[root@flower1 test]# git cat-file -p 68ab
100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad    hello.txt

四、樹層次結構:

    該節經過建立一個新的子目錄來看看Git是如何處理多個層次的目錄結構的:

[root@flower1 test]# pwd
/root/test
[root@flower1 test]# mkdir subdir
[root@flower1 test]# cp hello.txt subdir/hello.txt
[root@flower1 test]# git add subdir/hello.txt 
[root@flower1 test]# git write-tree
492413269336d21fac079d4a4672e55d5d2147ac
[root@flower1 test]# git cat-file -p 492413
100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad    hello.txt
040000 tree 68aba62e560c0ebc3396e8ae9335232cd93a3f60    subdir

能夠看到subdir的樹對象和以前的頂級目錄樹對象時徹底同樣的。

image

五、提交:

以前已經經過git add命令添加了hello.txt文件,並經過git write-tree命令生成了樹對象。

用下面的底層命令建立一個提交對象:git commit-tree SHA1

[root@flower1 test]# echo -n "Commit a file" | git commit-tree 492413269336d21fac079d4a4672e55d5d2147ac
204fa4469c1642cb9190048ebdc8fabc9a4a4af1

image

提交對象包含如下信息:

  • 標識關聯文件的樹對象的名稱
  • 創做新版本的人的名字和創做的時間
  • 把新版本放到版本庫的人的名字和提交的時間
  • 對本次修訂信息的說明(提交信息)

六、標籤:

    有2種基本的標籤類型:輕量級的和帶附註的。

    輕量級標籤只是一個提交對象的引用,一般被版本庫視爲是私用的。這些標籤並不在版本庫裏建立永久對象。

    帶附註的標籤會建立一個對象。

    能夠經過git tag命令來建立一個帶有提交信息、帶附註切未簽名的標籤:

[root@flower1 test]# git tag -m "Tag version 1.0" V1.0 204fa
image
相關文章
相關標籤/搜索