Git 暫存區的使用
一個健康的版本庫,是可閱讀,可追溯的。對於每一次提交,我們需要有清晰的把握。 Git 的暫存區(index),就是我們的得力工具。暫存區,就像是超市裏的購物車。 我們在貨架(工作區)上挑選商品(文件的修改),並帶到收銀臺結帳(提交)。 有了暫存區,我們可以對一大堆修改進行分門別類,先後有序的提交。
基本命令
對暫存區的操作,主要使用三個命令 add
、reset
、checkout
。
它們的作用分別爲:
-
add
將修改加入暫存區 -
reset
將修改從暫存區移出 -
checkout
放棄未加入暫存區的修改(從暫存區同步到工作區) 其中resset
和checkout
都是多用途的命令,分別還有另一個用途。reset
還可用於重置當前分支,checkout
還可用於重置 HEAD 並檢出文件。 區別在於若命令後跟提交(hash)或指向提交的指針(分支、tag 等), 則是重置分支和 HEAD 的功能; 命令後跟文件,或沒有參數,則是本文所說的用途。
精细操作 --patch
add
、reset
、checkout
三個命令都可以加 --patch
選項,簡寫爲 -p
。
遍歷每一處修改進行精細處理。
後面可以跟文件名作爲參數;也可以不加參數,表示對所有修改進行處理。
三個帶 -p
的命令組合使用,我給它起了個俗名,叫“3P 大法”。
是目前處理 git 暫存區的最理想方案。
執行命令將進入一個交互界面。大致如下:
最後一行的內容三個命令個有不同,分別爲:
說明了各自的用途。
這裏可見,git 展示了我們對 index.md 文件作出的一處修改。
並提供了 y,n,q,a,d,k,K,j,J,g,/,s,e,?
十一個可用的操作。分別表示什麼呢?
別的不清楚,但 ?
想必是用來提供幫助。我們輸入 ? Enter。
得到提示信息:
add
reset
checkout
初次看簡直眼花繚亂,讓我們整理一下:
基本使用只需要掌握 y
、n
、s
、q
,高級使用就再加上個 e
。
程序員一般有 y
、n
、s
、e
就夠用了。
導航命令則對於字典維護人員,webpack 配置師這樣的工種比較有用。
下面我們詳細講一下這個 e
。既然是 edit,自然需要 editor。
和不帶 -m
選項的 commit
一樣,它會調起編輯器,vim、nano 或是其它,依據你的配置。
內容如下:
以上展示了一處修改,我們刪除了 bar 行,並增加了 baz、qux 兩行。
@@ ... @@
中的內容展示了修改所在的行號和修改前後的行數。
緊接着是內容,在每行的行首第一個字符,表示行的類型,可以是 空格、-
、+
。
空格表示普通行,此行沒有修改;-
表示刪除的行,而 +
則表示新加的行。
注意,此空格不是縮進。若你使用縮進符,則非常清晰;若使用空格符代替縮進符,則要仔細了,要多一個空格。
此時,若保存退出編輯器,則表示應用(加入/移出/丟棄)此修改,相當於直接敲 y
。
若我們將修改還原,即刪除所有新加的行,即把刪除的行取消刪除,即將-
改爲空格,
則等於不應用此修改,相當於直接敲 n
。
若我們修改內容,則可以得到更多的效果。要注意不是所有修改都是允許的。
在 add
時,情況比較容易理解。例如我們修改爲如下的樣子:
表示我不刪除 bar 行,而刪除 foo 行。
baz 行的內容進行修改。而 qux 行則換個位置插入。
理解起來並不困難。
我們可以總結出規律:在 add
時,空格行和 -
行可以相互轉換,但的內容不能修改;
而 +
行則可隨意修改,刪除,還可以在任意地方插入。
而 reset
時,情況就和 add
相反了。空格行和 +
行可以相互轉換,但的內容不能修改;
而 -
行則可隨意修改,刪除,還可以在任意地方插入。
這讓人十分費解,還是用例子說明吧。還是上面的內容,我們作如下編輯:
我們得以“放棄”,“取消”這樣的字眼來分析。
我們將空格行 foo 改爲 +
行,表示取消對 foo 行的添加。
可 foo 行並非添加的,而是原來就在,所以就是刪除 foo 行囉。
刪除的 bar 行改爲 Bar 行,表示不放棄對 bar 行的刪除,而取消對 Bar 行的刪除。
那麼 bar 行還是要刪,然後添加 Bar 行。取消不存在的刪除,等於添加。即 bar 行改爲 Bar 行。
最後,放棄對 ET 行的刪除,也等於新插入一個 ET 行。
有點繞腦。有一個囫圇吞棗的辦法:reset 時,把 +
當 -
,把 -
當 +
就行了。
checkout
時,由於方向和 reset
一致,因此允許的修改和效果,都和 reset
一致,是反的。
區別只是 reset
改的是暫存區,而 checkout
改的是文件內容。
因此,可以 checkout
來做做實驗。躬行所悟,可比紙上所得要深刻百倍。
需要注意,對於新文件,add -p
是無效的,它會跳過這些文件,而 reset -p
則沒有這個問題。
對於新文件的 add
,必須整個文件進行操作。
整個文件操作和全局操作
通常,用 -p
瀏覽一遍到底提交了些什麼總是好的。
但也會有需要整文件操作,甚至全局操作的時候。
只是勿圖方便而濫用。
-
git add file
將文件中的全部修改加入暫存區 -
git reset file
將文件中的全部修改從暫存區移出 -
git checkout file
放棄文件中的全部未加入暫存區的修改 -
git add .
將文件中的全部修改加入暫存區 -
git reset
將暫存區中的全部修改移出(清空購物車) -
git checkout
全部未加入暫存區的修改
未完善的終極武器 add --interactive
git add 中,還有一個更加新潮的選項:--interactive
,簡寫爲 -i
。
顧名思義,這也是一個交互界面。樣子如下:
上方顯示 status
內容,與 git status
得到得主體內容差不多,列表得方式看起來更加清晰。
下方顯示可用的操作,一共有 8 個,此外還有個隱藏的 ?
,分別爲:
實際使用時,敲數字或首字母即可,無需鍵入完整命令。
其中 u
r
a
p
d
爲核心操作,執行後,會進入到二級界面,我們看到命令提示符由 >
變爲 >>
。
這時候,我們可以選取要操作的文件。可用序號選擇,也可輸入文件名(前面一段,沒有重複即可)。
目前,文件名還不支持分段匹配、模糊匹配、*
?
,也不支持 tab 鍵輸入提示,和上下鍵輸入歷史,希望將來能有。
但序號也夠用了。在所選的序號或文件名前加 -
則表示取消選擇。第一次回車,執行選擇,然後可以繼續選擇。
第二次回車,執行操作。
add --interactive
給了我們一個很棒的操作方式,我們可流暢地操作,不必一而再再而三地執行 git status
。
就操作方式而言,可以說是終極武器。然而這個未來的終極武器還有需多不夠完善之處。
它有 add file
、reset file
以及 add -p file
卻缺少了 reset -p file
、checkout file
、checkout -p file
。
可以說只整合了一半的功能。最關鍵的 add -p file
和 reset -p file
,就少了一個。
我們只能先 reset file
再 add -p file
。若文件中有很多修改,這會相當麻煩。
因此,這個命令還需要觀望。目前最佳方案,還是三個 patch,俗稱 3P 大法。