git 乾貨系列:(二)深入學習之前先理解 git 暫存區

嘟嘟MD發表於2017-05-23

原本地址:git乾貨系列:(二)深入學習之前先理解git暫存區
部落格地址:tengj.top/

前言


暫存區(stage, index)Git最重要的概念之一,理解了這個概念很多 Git 命令就不再那麼神祕了。下面幾個驗證例子一開始看不懂沒關係,工作區、版本庫中的暫存區和版本庫之間的關係圖先理解先。

正文


下面這個圖展示了工作區、版本庫中的暫存區和版本庫之間的關係。

git 乾貨系列:(二)深入學習之前先理解 git 暫存區

在這個圖中,我們可以看到部分 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 checkout . 或者 git checkout -- [file] 命令時,會用暫存區全部或指定的檔案替換工作區的檔案。這個操作很危險,會清除工作區中未新增到暫存區的改動。
  • 當執行 git checkout HEAD . 或者 git checkout HEAD [file] 命令時,會用 HEAD 指向的 master 分支中的全部或者部分檔案替換暫存區和以及工作區中的檔案。這個命令也是極具危險性的,因為不但會清除工作區中未提交的改動,也會清除暫存區中未提交的改 動。
  • 當執行 git rm --cached [file]命令時,會直接從暫存區刪除檔案,工作區則不做出改變。
  • 當執行 git rm file命令時,會同時刪除暫存區和工作區的檔案。
  • 當執行 rm file命令時,只會刪除工作區的檔案。

下面舉例子來證明以上觀點


假設:
工作區:a
暫存區(index):b
HEAD:C

git diff命令結論

git diff           比較a跟b
git diff --cached  比較b跟c
git diff HEAD      比較a跟c複製程式碼

git reset跟 git checkout結論

git reset HEAD              c覆蓋b
git checkout -- <file>      b覆蓋a
git checkout HEAD <file>    c覆蓋a,b複製程式碼

git rm命令結論

 git rm          刪除a跟b
 git rm --cached 只刪除b
 rm file         只刪除a複製程式碼

證明git diff結論


例子,預設新建一個readme.txt,裡面輸入內容one然後add並且commit一次。

1:修改readme.txt,新增內容two,這時候a內容改變了,多了two,而b跟c內容不變,都只有one
執行git diff readme.txt檢視效果

git 乾貨系列:(二)深入學習之前先理解 git 暫存區

結論:如圖看出,內容有修改, a跟b比較了


執行git diff --cached readme.txt檢視效果

git 乾貨系列:(二)深入學習之前先理解 git 暫存區

結論:如圖看出,沒有變化,因為b跟c內容一樣。


執行git diff HEAD readme.txt檢視效果

git 乾貨系列:(二)深入學習之前先理解 git 暫存區

如圖所示:內容有修改,a跟c比較了


2.這時候執行git add readme.txt,這時候a,b內容都多了two,而c內容不變,只有one
執行git diff readme.txt檢視效果

git 乾貨系列:(二)深入學習之前先理解 git 暫存區

結論:如圖看出,沒有變化, 因為a跟b內容一樣。


執行git diff --cached readme.txt檢視效果

git 乾貨系列:(二)深入學習之前先理解 git 暫存區

結論:如圖看出,內容有修改,b跟c比較了


執行git diff HEAD readme.txt檢視效果

git 乾貨系列:(二)深入學習之前先理解 git 暫存區

結論:如圖看出,內容有修改,a跟c比較了

3.最後使用git commit提交一次,這時候a,b,c內容都一樣,都包含two

git 乾貨系列:(二)深入學習之前先理解 git 暫存區

結論,如圖看出,沒有變化,說明a,b,c內容一樣


根據上面的例項再一次證明了如下觀點:

git diff           比較工作區跟暫存區
git diff --cached  比較暫存區跟HEAD
git diff HEAD      比較工作區跟HEAD複製程式碼

證明git reset跟 git checkout結論


例子,預設新建一個readme.txt,裡面輸入內容one然後add並且commit一次,這時候a,b,c內容都是one


1.修改readme.txt,新增內容two,執行git add readme.txt操作,這時候a ,b內容都多了two,c還是隻有one.
執行git reset HEAD -- readme.txt命令後,c覆蓋b,這時候b內容也變成只有one了,使用git diff readme.txt命令可以看到,有內容修改,a跟b內容不一樣。

git 乾貨系列:(二)深入學習之前先理解 git 暫存區


2.此時a內容有two,b和c都只有one,執行git checkout -- readme.txt後,b覆蓋a,此時a,b,c都是one。執行git diff readme.txt命令可以看到,沒有改變。

git 乾貨系列:(二)深入學習之前先理解 git 暫存區


3.此時a,b,c都只有one,修改一下,新增內容two,執行git add readme.txtgit commit -m "two".再修改一次readme.txt,新增內容three,然後會執行git add readme.txt,此時a跟b都包含three,而c只包含one跟two。執行git checkout HEAD readme.txt後,c覆蓋a和b,a,b裡面內容都只有one跟two。分別使用命令git diff --cachedgit diff HEAD來檢視b跟c,a跟c的比對,發現都一樣。

git 乾貨系列:(二)深入學習之前先理解 git 暫存區


根據上面的例項再一次證明了如下觀點:

git reset HEAD              HEAD覆蓋暫存區
git checkout -- <file>      暫存區覆蓋工作區
git checkout HEAD <file>    HEAD覆蓋暫存區和工作區複製程式碼

證明git rm 結論


預設新建一個readme.txt,裡面輸入內容one,然後使用git add readme.txt命令。
1.執行git rm readme.txt命令,發現檔案被刪除了。

2.再新建一個一個readme.txt,裡面輸入內容 one,然後使用git add readme.txt命令。執行git rm --cached readme.txt命令,發現檔案內readme.txt還在,然後執行git status命令,發現是Untracked狀態,也就是未add,這就說明暫存區被刪除了。

git 乾貨系列:(二)深入學習之前先理解 git 暫存區


根據上面的例項再一次證明了如下觀點:

 git rm file      會將檔案從快取區和你的硬碟中(工作區)刪除
 git rm --cached  只刪除暫存區,不刪除工作區
 rm file          只刪除工作區複製程式碼

總結


暫存區的原理需要大家重複的加深瞭解,基礎打牢了後面學起來就輕鬆很多,上面幾個例子都自己驗證一遍,加深印象。


一直覺得自己寫的不是技術,而是情懷,一篇篇文章是自己這一路走來的痕跡。靠專業技能的成功是最具可複製性的,希望我的這條路能讓你少走彎路,希望我能幫你抹去知識的蒙塵,希望我能幫你理清知識的脈絡,希望未來技術之巔上有你也有我。

相關文章