1. 程式人生 > >Git學習筆記(三) Git暫存區

Git學習筆記(三) Git暫存區

檢視工作區檔案的改動

$ git diff 工作區與提交任務(提交暫存區,stage)中相比的差異

$ git diff HEAD 工作區和HEAD(當前工作分支)相比的差異

$ git diff --cached (或--staged)提交暫存區(提交任務,stage)和版本庫中檔案的差異

$ git status 顯示狀態 -s表示用精簡方式 -b同時顯示當前工作分支的名稱

其中標識有兩列,拿狀態M來說

第一列含義是:版本庫中的檔案與處於中間狀態——提交任務(提交暫存區,stage)中的檔案相比有改動

第二列含義是:工作區當前的檔案與處於中間狀態——提交任務(提交暫存區,stage)中的檔案相比有改動

檔案./git/index實際上是一個包含檔案索引的目錄樹,像一個虛擬的工作區。在這個虛擬工作區的目錄樹中,記錄了檔名和檔案的狀態資訊(時間戳和檔案長度等)。檔案的內容並沒有儲存在其中,而是儲存在Git物件庫.git/objects目錄中,檔案索引建立了檔案和物件庫中物件實體之間的對應。

圖中左側為工作區,右側為版本庫。在版本庫中標記為 "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 分支中的全部或者部分檔案替換暫存區和以及工作區中的檔案。這個命令也是極具危險性的,因為不但會清除工作區中未提交的改動,也會清除暫存區中未提交的改動。

目錄樹的瀏覽

$ git ls-tree -l HEAD 檢視HEAD(版本庫中當前提交)指向的目錄樹 -l引數可以顯示檔案大小

輸出的檔案條目從左至右,第一個欄位是檔案的屬性,第二個欄位(blob)說明是Git物件庫中的一個blob物件(檔案),第三個欄位是該檔案在物件庫中對應的ID——一個40位的SHA1雜湊值格式的ID,第四個欄位是檔案大小,第五個欄位是檔名。

在瀏覽暫存區的目錄樹之前,首先清除工作區當前的改動。

$ git clean -fd 清除當前工作區中沒有加入版本庫的檔案和目錄(非跟蹤檔案和目錄),然後執行$ git checkout .命令,用暫存區內容重新整理工作區。

$ git ls-files -s 顯示暫存區的目錄樹,其中第三個欄位不是檔案大小而是暫存區編號

若想針對暫存區的目錄樹使用git ls-tree命令,需要先將暫存區的目錄樹寫入Git物件庫,然後針對該目錄樹執行git ls-tree命令

$ git write-tree 輸出的就是寫入Git物件庫的TreeID,這個ID將作為下一條命令的輸入

5b873f747ccb268e4491f289eb37fc675ff5825b

$ git ls-tree -l 5b873f747 只需寫前幾位,只要不與其他物件的ID衝突即可

100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad      12test

可以看出到處都是40位的SHA1雜湊值格式的ID,可以用於指代檔案內容(blob)、目錄樹(tree)和提交。

$ git write-tree | xargs git ls-tree -l -r -t 遞迴顯示目錄內容使用-r引數,顯示遞迴過程中遇到的每棵樹而不是隻顯示最終檔案使用-t引數

不要使用git commit -a

帶上此引數,對本地所有變更的檔案執行提交操作,包括對本地修改的檔案和刪除的檔案,但不包括未被版本庫跟蹤的檔案。可以簡化一些操作,減少用git add命令標識變更檔案的步驟,但是丟掉了對提交內容進行控制的能力。

儲存當前工作進度

$ git stash 執行完此命令後再檢視工作區狀態,會發現工作區尚未提交的改動(包括暫存區的改動)全都不見了