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

本來地址:git乾貨系列:(二)深刻學習以前先理解git暫存區
博客地址:tengj.top/git

前言


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

正文


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


在這個圖中,咱們能夠看到部分 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命令結論spa

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

git reset跟 git checkout結論3d

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

git rm命令結論code

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

證實git diff結論


例子,默認新建一個readme.txt,裏面輸入內容one而後add而且commit一次。cdn

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

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


執行git diff --cached readme.txt查看效果

結論:如圖看出,沒有變化,由於b跟c內容同樣。


執行git diff HEAD readme.txt查看效果

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


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

結論:如圖看出,沒有變化, 由於a跟b內容同樣。


執行git diff --cached readme.txt查看效果

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


執行git diff HEAD readme.txt查看效果

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

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

結論,如圖看出,沒有變化,說明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內容不同。


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


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 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 rm file      會將文件從緩存區和你的硬盤中(工做區)刪除
 git rm --cached  只刪除暫存區,不刪除工做區
 rm file          只刪除工做區複製代碼

總結


暫存區的原理須要你們重複的加深瞭解,基礎打牢了後面學起來就輕鬆不少,上面幾個例子都本身驗證一遍,加深印象。


一直以爲本身寫的不是技術,而是情懷,一篇篇文章是本身這一路走來的痕跡。靠專業技能的成功是最具可複製性的,但願個人這條路能讓你少走彎路,但願我能幫你抹去知識的蒙塵,但願我能幫你理清知識的脈絡,但願將來技術之巔上有你也有我。

相關文章
相關標籤/搜索