git暫存區的理解


git暫存區的理解

一、總結

一句話總結:

.git/index就是git的暫存區,是一個包含文件索引的目錄樹,記錄了文件名、文件的狀態信息(時間戳、文件長度等),文件的內容並不存儲其中
文件的內容並不存儲.git/index,而是保存在 Git 對象庫(.git/objects)中,文件索引建立了文件和對象庫中對象實體之間的對應

文件.git/index 實際上就是一個包含文件索引的目錄樹,像是一個虛擬的工作區。在這個虛擬工作區的目錄樹中,記錄了文件名、文件的狀態信息(時間戳、文件長度等),
文件的 內容並不存儲其中,而是保存在 Git 對象庫(.git/objects)中,文件索引建立了文件和對象庫中對象實體之間的對應。下面這個圖展示了工作區、版本庫中的暫存區和版本庫之間的關 系。

 

 

二、git暫存區的理解

轉自或參考:git暫存區的理解
https://www.cnblogs.com/brothertao/archive/2011/04/01/2002444.html

 

暫存區(stage, index)是 Git 最重要的概念之一,理解了這個概念很多 Git 命令就不再那么神秘了。

今天在寫這部分的內容,畫了一個圖,看看有沒有什么問題。

理解 Git 暫存區(stage)

把上面的“實踐二”從頭至尾走一遍,不知道您的感想如何?

  • —— “被眼花繚亂的 Git 魔法徹底搞糊塗了?”
  • —— “Git 為什么這么折磨人,修改的文件直接提交不就完了么?”
  • —— “看不出 Git 這么做有什么好處?”

在“實踐二”的過程中,我有意無意的透漏了“暫存區”的概念,為了避免用戶被新概念嚇壞,在暫存區出現的地方用同時使用了“提交任務”這一更易理解 的概念,但是暫存區(stage, 或稱為 index)才是其真正的名稱。我認為 Git 暫存區(stage, 或稱為 index)的設計是 Git 最成功的設計之一,也是最難理解的一個設計。

在版本庫(.git)目錄下,有一個 index 文件,我們針對這個文件做一個有趣的試驗。

首先我們執行 “git checkout” 命令撤銷工作區中welcome.txt 文件尚未提交的修改。

$ git checkout -- welcome.txt
$ git status -s

我們通過狀態輸出,看以看到工作區已經沒有改動了。我們查看一下.git/index 文件,注意該文件的時間戳(19:37:44):

$ ls --full-time .git/index
-rw-r--r-- 1 jiangxin jiangxin 112 2010-11-29 19:37:44.625246224 +0800 .git/index

我們再次執行 “git status” 命令,然后顯示.git/index 文件的時間戳(19:37:44),和上面的一樣。

$ git status -s
$ ls --full-time .git/index
-rw-r--r-- 1 jiangxin jiangxin 112 2010-11-29 19:37:44.625246224 +0800 .git/index

現在我們更改一下 welcome.txt 的時間戳,但是不改變它的內容。然后再執行 “git status” 命令,然后查看.git/index 文件時間戳(19:42:06)。

$ touch welcome.txt
$ git status -s
$ ls --full-time .git/index
-rw-r--r-- 1 jiangxin jiangxin 112 2010-11-29 19:42:06.980243216 +0800 .git/index

看到了么,時間戳改變了!

這個試驗說明當執行 “git status” 命令掃描工作區改動的時候,先依據.git/index 文件中記錄的(工作區跟蹤文件的)時間戳、長度等信息判斷工作區文件是否改變。如果工作區的文件時間戳改變,說明文件的內容 可能 被改變了,需要要打開文件,讀取文件內容,和更改前的原始文件相比較,判斷文件內容是否被更改。如果文件內容沒有改變,則將該文件新的時間戳記錄到.git/index 文件中。因為判斷文件是否更改,使用時間戳、文件長度等信息進行比較要比通過文件內容比較要快的多,所以 Git 這樣的實現方式可以讓工作區狀態掃描更快速的執行,這也是 Git 高效的因素之一。

文件.git/index 實際上就是一個包含文件索引的目錄樹,像是一個虛擬的工作區。在這個虛擬工作區的目錄樹中,記錄了文件名、文件的狀態信息(時間戳、文件長度等),文件的 內容並不存儲其中,而是保存在 Git 對象庫(.git/objects)中,文件索引建立了文件和對象庫中對象實體之間的對應。下面這個圖展示了工作區、版本庫中的暫存區和版本庫之間的關 系。

 

 

工作區、版本庫、暫存區原理圖

在這個圖中,我們可以看到部分 Git 命令是如何影響工作區和暫存區(stage, index)的。

  • 圖中左側為工作區,右側為版本庫。在版本庫中標記為 “index” 的區域是暫存區(stage, index),標記為 “master” 的是 master 分支所代表的目錄樹。
  • 圖中我們可以看出此時 “HEAD” 實際是指向 master 分支的一個“游標”。所以圖示的命令中出現 HEAD 的地方可以用 master 來替換。
  • 圖中的 objects 標識的區域為 Git 的對象庫,實際位於 “.git/objects” 目錄下,我們會在后面的章節重點介紹。
  • 當對工作區修改(或新增)的文件執行 “git add” 命令時,暫存區的目錄樹被更新,同時工作區修改(或新增)的文件內容被寫入到對象庫中的一個新的對象中,而該對象的ID 被記錄在暫存區的文件索引中。
  • 當執行提交操作(git commit)時,暫存區的目錄樹寫到版本庫(對象庫)中,master 分支會做相應的更新。即 master 指向的目錄樹就是提交時暫存區的目錄樹。
  • 當執行 “git reset HEAD” 命令時,暫存區的目錄樹會被重寫,被 master 分支指向的目錄樹所替換,但是工作區不受影響。
  • 當執行 “git rm –cached <file>” 命令時,會直接從暫存區刪除文件,工作區則不做出改變。
  • 當執行 “git checkout .” 或者 “git checkout — <file>” 命令時,會用暫存區全部或指定的文件替換工作區的文件。這個操作很危險,會清除工作區中未添加到暫存區的改動。
  • 當執行 “git checkout HEAD .” 或者 “git checkout HEAD <file>” 命令時,會用 HEAD 指向的 master 分支中的全部或者部分文件替換暫存區和以及工作區中的文件。這個命令也是極具危險性的,因為不但會清除工作區中未提交的改動,也會清除暫存區中未提交的改 動。

分割線------------------------------------------------------------------------------------------------------------------------------

注解:

1:git checkout命令不同的git版本間效果不同,經測試,1.7.4,此命令不會刪除未跟蹤狀態(untracked)的文件。

2:不是很同意理解成三個區域

3:我的理解方式:

image

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM