歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux索引與提交的那些事

Linux索引與提交的那些事

日期:2017/2/25 10:37:28   编辑:Linux教程

不一樣的索引

  Git 索引是一個在你的工作目錄(working tree)和項目倉庫間的暫存區域(staging area)。有了它, 你可以把許多內容的修改一起提交(commit)。 如果你創建了一個提交(commit),那麼提交的一般是暫存區裡的內容, 而不是工作目錄中的內容。

  一個Git項目中文件的狀態大概分成下面的兩大類,而第二大類又分為三小類:

  1、未被跟蹤的文件(untracked file)

  2、已被跟蹤的文件(tracked file)

  1、被修改但未被暫存的文件(changed but not updated或modified)

  2、已暫存可以被提交的文件(changes to be committed 或staged)

  3、自上次提交以來,未修改的文件(clean 或 unmodified)

  看到上面的這麼多的規則,大家早就頭大了吧。老辦法,我們建一個Git測試項目來試驗一下:

  我們先來建一個空的項目:

  $rm -rf stage_proj

  $mkdir stage_proj

  $cd stage_proj

  $git init

  Initialized empty Git repository in /home/test/work/test_stage_proj/.git/我們還創建一個內容是“hello, world”的文件:

  $echo "hello,world" > readme.txt現在來看一下當前工作目錄的狀態,大家可以看到“readme.txt”處於未被跟蹤的狀態(untracked file):

  $git status

  # On branch master

  #

  # Initial commit

  #

  # Untracked files:

  # (use "git add …" to include in what will be committed)

  #

  # readme.txt

  nothing added to commit but untracked files present (use "git add" to track)把“readme.txt"加到暫存區: $git add readme.txt

  現在再看一下當前工作目錄的狀態:

  $git status

  # On branch master

  #

  # Initial commit

  #

  # Changes to be committed:

  # (use "git rm --cached …" to unstage)

  #

  nothing to commit (working directory clean)大家可以看到“nothing to commit (working directory clean)”;如果一個工作樹(working tree)中所有的修改都已提交到了當前分支裡(current head),那麼就說它是干淨的(clean),反之它就是髒的(dirty)。

  SHA1值內容尋址

  正如Git is the next Unix 一文中所說的一樣,Git是一種全新的使用數據的方式(Git is a totally new way to operate on data)。Git把它所管理的所有對象(blob,tree,commit,tag……),全部根據它們的內容生成SHA1哈希串值作為對象名;根據目前的數學知識,如果兩塊數據的SHA1哈希串值相等,那麼我們就可以認為這兩塊數據是相同 的。這樣會帶來的幾個好處:

  Git只要比較對象名,就可以很快的判斷兩個對象的內容是否相同。

  因為在每個倉庫(repository)的“對象名”的計算方法都完全一樣,如果同樣的內容存在兩個不同的倉庫中,就會存在相同的“對象名”。

  Git還可以通過檢查對象內容的SHA1的哈希值和“對象名”是否匹配,來判斷對象內容是否正確。

  我們通過下面的例子,來驗證上面所說的是否屬實。現在創建一個和“readme.txt“內容完全相同的文件”readme2.txt“,然後再把它提交到本地倉庫中:

  $echo "hello,world" > readme2.txt

  $git add readme2.txt

  $git commit -m "add new file: readme2.txt"

  [master 6200c2c] add new file: readme2.txt

  1 files changed, 1 insertions(+), 0 deletions(-)

  create mode 100644 readme2.txt下面的這條很復雜的命令是查看當前的提交(HEAD)所包含的blob對象:

  $git cat-file -p HEAD | head -n 1 | cut -b6-15 | xargs git cat-file -p

  100644 blob 2d832d9044c698081e59c322d5a2a459da546469 readme.txt

  100644 blob 2d832d9044c698081e59c322d5a2a459da546469 readme2.txt我們再來看看上一次提交(HEAD^)所包含的blob對象:

  $git cat-file -p HEAD^ | head -n 1 | cut -b6-15 | xargs git cat-file -p

  100644 blob 2d832d9044c698081e59c322d5a2a459da546469 readme.txt很明顯大家看到盡管當前的提交比前一次多了一個文件,但是它們之間卻是在共用同一個blob對象:“2d832d9”。

  No delta, just snapshotGit 與大部分你熟悉的版本控制系統,如Subversion、CVS、Perforce 之間的差別是很大的。傳統系統使用的是: “增量文件系統” (Delta Storage systems),它們存儲是每次提交之間的差異。而Git正好與之相反,它是保存的是每次提交的完整內容(snapshot);它會在提交前根據要提交 的內容求SHA1哈希串值作為對象名,看倉庫內是否有相同的對象,如果沒有就將在“。git/objects"目錄創建對應的對象,如果有就會重用已有的 對象,以節約空間。

  下面我們來試驗一下Git是否真的是以“snapshot”方式保存提交的內容。

  先修改一下"readme.txt",給裡面加點內容,再把它暫存,最後提交到本地倉庫中:

  $echo "hello,world2" 》 readme.txt

  $git add readme.txt

  $git commit -m "add new content for readme.txt"

  [master c26c2e7] add new content for readme.txt 1 files changed, 1 insertions(+), 0 deletions(-)我們現在看看當前版本所包含的blob對象有哪些:

  $git cat-file -p HEAD | head -n 1 | cut -b6-15 | xargs git cat-file -p

  100644 blob 2e4e85a61968db0c9ac294f76de70575a62822e1 readme.txt

  100644 blob 2d832d9044c698081e59c322d5a2a459da546469 readme2.txt從上面的命令輸出,我們可以看到"readme.txt"已經對應了一個新的blob對象:“2e4e85a”,而之前版本的"readme.txt“對應的blob對象是:“2d832d9”。下面我們再來看一看這兩個”blob“裡面的內容和我們的預期是否相同:

  $git cat-file -p 2e4e85a

  hello,world

  hello,world2

  $git cat-file -p 2d832d9

  hello,world大家可以看到,每一次提交的文件內容還是全部保存的(snapshot)。

  小結

  Git內在機制和其它傳統的版本控制系統(VCS)間存在本質的差異,所以Git的裡"add"操作的含義和其它VCS存在差別也不足為奇,“git add“不但能把未跟蹤的文件(untracked file)添加到版本控制之下,也可以把修改了的文章暫存到索引中。

  同時,由於采用“SHA1哈希串值內容尋值“和”快照存儲(snapshot)“,讓Git成為一個速度非常非常快的版本控制系統(VCS)。

Copyright © Linux教程網 All Rights Reserved