Git三大特色之Stage(暫存區)

NO IMAGE

這是開篇

有人說,暫存區是 Git 最精彩的設計,同時也是最難理解的部分,兩者我都感覺不太明顯,但當我想寫關於暫存區的理解後,發現的確不怎麼好講,這個玩意,有點只可意會的感覺,用 Git 用熟練了,很自然體會到暫存區設計的精彩之處。

在我看來,學習其他命令之前,對暫存區有一個概念和大概理解是非常重要的,因為,很多命令都涉及到了它。

為什麼 commit 之前要先 add 一下呢?

我在剛接觸 Git 命令的時候,對 Git 沒什麼概念,就是趕鴨子上線式的學習,用到什麼,就去 Google 什麼,例如第一天我搜索的就是“git first commit”,然後搜到很多 Git 的初級教程,幾乎都有說先執行 git add ,然後 git commit。在我照著教程一步步 add & commit 的時候,我就在想,commit 就 commit唄,為什麼 commit 之前必須要 add 一下呢?

當時才疏學淺,不敢胡亂嘗試,擔心試錯了整不回來原來的樣子。現在膽子大了些,決定嘗試一下沒有 add 的 commit。

通過 echo 命令給 master.txt 文件加了一行內容,然後執行提交:

Git三大特色之Stage(暫存區)

Git三大特色之Stage(暫存區)

測試結果很明顯,commit 失敗,失敗原因是沒有可以提交的修改,然而奇怪的是,查看 master.txt 文件,內容卻已經添加成功。
好在 Git 非常貼心的給了我們詳細的錯誤說明,下面仔細看一下:

On branch master
Changes not staged for commit:
	modified:   master.txt

no changes added to commit

英語渣的我最近熱衷於翻譯:

在 master 分支
修改沒有被暫存起來以備提交
	修改:   master.txt

沒有可以提交的修改

從這個提示信息中,我似乎嗅到了一絲絲的真(jian)相(qing),commit 時檢測是否有修改的 master.txt,好像不是我看到的 master.txt。那我看到 master.txt 是什麼?我沒看到的又是什麼?而且它在哪裡?

答案就比較明顯了,肯定在 Git 的暫存區(不然我為啥要舉這個例子,哈哈)。

git commit 執行時,會提交暫存區的內容。git add 命令會將我們看到的修改添加到暫存區中,這就是為什麼 git commit 之前要先執行 git add 的原因。

接著上面的問題,思維稍微發散一下,還可以問出很多問題,例如,add 將修改放入暫存區,那麼 add 之前數據存放在哪裡?commit 又將存儲區的數據提交到什麼地方了呢?以及為什麼要這麼分為幾個存儲部分?等看完這篇博客,希望你這些問題,都能找到答案。

Git 可以大概分為三個區

Git 本地數據管理,大概可以分為三個區,工作區,暫存區和版本庫。

  • 工作區(Working Directory)
    是我們直接編輯的地方,例如 Android Studio 打開的項目,記事本打開的文本等,肉眼可見,直接操作。
  • 暫存區(Stage 或 Index)
    數據暫時存放的區域,可在工作區和版本庫之間進行數據的友好交流。
  • 版本庫(commit History)
    存放已經提交的數據,push 的時候,就是把這個區的數據 push 到遠程倉庫了。

下面是,當開發者通過 git 修改數據時,各區之間的數據傳遞流程示意圖。

Git三大特色之Stage(暫存區)

為了驗證以上流程的正確性,我們可以自己動手實驗一下,為了對比三個區之間的數據差別,過程中,可以藉助神奇的 diff 命令。

命令作用
git diff工作區 vs 暫存區
git diff head工作區 vs 版本庫
git diff –cached暫存區 vs 版本庫

現在三個區的數據是一致的,執行 git diff 命令都為空

命令接果
(工作區 vs 暫存區)git diff
Git三大特色之Stage(暫存區)
(工作區 vs 版本庫)git diff head
Git三大特色之Stage(暫存區)
(暫存區 vs 版本庫)git diff –cached
Git三大特色之Stage(暫存區)

然後給 master.txt 添加一行內容後,現在工作區內容發生變化,暫存區和版本庫內容不變。

Git三大特色之Stage(暫存區)

命令接果
(工作區 vs 暫存區)git diff
Git三大特色之Stage(暫存區)
(工作區 vs 版本庫)git diff head
Git三大特色之Stage(暫存區)
(暫存區 vs 版本庫)git diff –cached
Git三大特色之Stage(暫存區)

執行git add 操作後,修改同步到暫存區,現在工作區和暫存區數據一致。

Git三大特色之Stage(暫存區)

命令接果
(工作區 vs 暫存區)git diff
Git三大特色之Stage(暫存區)
(工作區 vs 版本庫)git diff head
Git三大特色之Stage(暫存區)
(暫存區 vs 版本庫)git diff –cached
Git三大特色之Stage(暫存區)

執行 git commit 操作後,修改已經同步到版本庫,三區數據再次保持一致。

Git三大特色之Stage(暫存區)

命令接果
(工作區 vs 暫存區)git diff
Git三大特色之Stage(暫存區)
(工作區 vs 版本庫)git diff head
Git三大特色之Stage(暫存區)
(暫存區 vs 版本庫)git diff –cached
Git三大特色之Stage(暫存區)

Stage 賦予 Git 更多靈活性

不知道時,你對它可能毫無所感。知道後,你一定會感動地想哭,並十分之膜拜 Git 的開發者- Linus Torvalds ,stage 就是這麼精彩的玩意。以下看起來比較束手無策的場景,只要理解 stage,用好相應命令,都能輕易解決:

  • 修改了4個文件,在不放棄任何修改的情況下,其中一個文件不想提交,如何操作?(沒add : git add 已經add: git reset –soft )
  • 修改到一半的文件,突然間不需要或者放棄修改了,怎麼恢復未修改前文件? (git checkout)
  • 代碼寫一半,被打斷去做其他功能開發,未完成代碼保存?(git stash)
  • 代碼寫一半,發現忘記切換分支了?(git stash & git checkout)
  • 代碼需要回滾了?(git reset)
  • 等等

上面提到的 checkout & stash & reset 等命令,通過不同的參數搭配使用,可以在工作區,暫存區和版本庫之間,輕鬆進行數據的來回切換。

例如前篇 Branch 博客用到的 git reset 回滾命令,帶上不同參數就有不同的作用,如下:

命令作用
git reset –soft暫存區->工作區
git reset –mixed版本庫->暫存區
git reset –hard版本庫->暫存區->工作區

完事大家可以自己新建一個測試 Demo,多嘗試一下,相信你會因為暫存區的存在更加地喜歡 Git。

這是結尾

暫存區是介於工作區和版本庫之間的一箇中間存儲狀態,很多命令都會涉及暫存區的狀態,因此理解暫存區這一個存在是至關重要的。

希望這篇文章能給你的 Git 學習帶來幫助,同時,如有錯誤之處還望指出,下篇博客見,see you next blog!


Git三大特色之Stage(暫存區)

歡迎關注博主的微信公眾號,快快加入哦,期待與你一起成長!

相關文章

Gitrebase黑魔法之打磨commit顆粒度

Gitrebase黑魔法之打造完美的線性歷史

Git用cherrypick挑好看的小櫻桃

Git三大特色之WorkFlow(工作流)