1. 程式人生 > 其它 >《精通git》筆記之八(選擇修訂版本、互動式暫存)

《精通git》筆記之八(選擇修訂版本、互動式暫存)

技術標籤:運維git

選擇修訂版本

簡短的 SHA-1

Git 十分智慧,只需要提供 SHA-1 的前幾個字元就可以獲得對應的那次提交,當然,提供的 SHA-1 字元數量不得少於 4 個,並且沒有歧義——也就是說,當前倉庫中只有一個物件以這段 SHA-1 開頭。
例如檢視一次指定的提交,假設執行 git log 命令來檢視之前新增一個功能的那次提交:

$ git log
commit 734713bc047d87bf7eac9674765ae793478c50d3
Author: Scott Chacon <[email protected]>
Date: Fri Jan 2 18:32:33 2009 -0800
    fixed refs handling, added gc auto, updated tests
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Merge: 1c002dd... 35cfb2b...
Author: Scott Chacon <
[email protected]
> Date: Thu Dec 11 15:08:43 2008 -0800 Merge commit 'phedders/rdocs' commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b Author: Scott Chacon <[email protected]> Date: Thu Dec 11 14:58:32 2008 -0800 added some blame and merge stuff

假設這個提交是 1c002dd…,如果想 git show 這個提交,下面的命令是等價的(假設簡短的版本沒有歧

義):

$ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b
$ git show 1c002dd4b536e7479f
$ git show 1c002d

Git 可以為 SHA-1 值生成出簡短且唯一的縮寫。
通常 8 到 10 個字元就已經足夠在一個專案中避免 SHA-1 的歧義。

分支引用

指明一次提交最直接的方法是有一個指向它的分支引用。這樣就可以在任意一個 Git 命令中使用這個分支名來代替對應的提交物件或者 SHA-1 值。例如,想要檢視一個分支的最後一次提交的物件,假設 topic1 分支指向 ca82a6d ,那麼以下的命令是等價的:

$ git show ca82a6dff817ec66f44342007202690a93763949
$ git show topic1

如果想知道某個分支指向哪個特定的 SHA-1,或者想看任何一個例子中被簡寫的 SHA-1 ,可以使用一個叫做 rev-parse 的 Git 探測工具。可以在你的分支上執行 rev-parse

$ git rev-parse topic1
ca82a6dff817ec66f44342007202690a93763949
引用日誌

當工作時, Git 會在後臺儲存一個引用日誌(reflog),引用日誌記錄了最近幾個月你的 HEAD 和分支引用所
指向的歷史。
可以使用 git reflog 來檢視引用日誌

$ git reflog
734713b [email protected]{0}: commit: fixed refs handling, added gc auto, updated
d921970 [email protected]{1}: merge phedders/rdocs: Merge made by recursive.
1c002dd [email protected]{2}: commit: added some blame and merge stuff
1c36188 [email protected]{3}: rebase -i (squash): updating HEAD
95df984 [email protected]{4}: commit: # This is a combination of two commits.
1c36188 [email protected]{5}: rebase -i (squash): updating HEAD
7e05da5 [email protected]{6}: rebase -i (pick): updating HEAD

每當 HEAD 所指向的位置發生了變化,Git 就會將這個資訊儲存到引用日誌這個歷史記錄裡。通過這些數
據,可以很方便地獲取之前的提交歷史。如果想檢視倉庫中 HEAD 在五次前的所指向的提交,可以使用 @{n} 來引用 reflog 中輸出的提交記錄。

$ git show [email protected]{5}

同樣可以使用這個語法來檢視某個分支在一定時間前的位置。例如,檢視的 master 分支在昨天的時候指向了哪個提交,你可以輸入

$ git show [email protected]{yesterday}

就會顯示昨天該分支的頂端指向了哪個提交。這個方法只對還在引用日誌裡的資料有用。
可以執行 git log -g 來檢視類似於 git log 輸出格式的引用日誌資訊:

$ git log -g master
commit 734713bc047d87bf7eac9674765ae793478c50d3
Reflog: [email protected]{0} (Scott Chacon <[email protected]>)
Reflog message: commit: fixed refs handling, added gc auto, updated
Author: Scott Chacon <[email protected]>
Date: Fri Jan 2 18:32:33 2009 -0800
    fixed refs handling, added gc auto, updated tests
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Reflog: [email protected]{1} (Scott Chacon <[email protected]>)
Reflog message: merge phedders/rdocs: Merge made by recursive.
Author: Scott Chacon <[email protected]>
Date: Thu Dec 11 15:08:43 2008 -0800
    Merge commit 'phedders/rdocs'

值得注意的是,引用日誌只存在於本地倉庫,一個記錄你在你自己的倉庫裡做過什麼的日誌。其他人拷貝的倉庫裡的引用日誌不會和你的相同;而新克隆一個倉庫的時候,引用日誌是空的,因為你在倉庫裡還沒有操作。
git show [email protected]{2.months.ago} 這條命令只有在你克隆了一個專案至少兩個月時才會有用——如果
是五分鐘前克隆的倉庫,那麼它將不會有結果返回。

祖先引用

祖先引用是另一種指明一個提交的方式。如果在引用的尾部加上一個 ^, Git 會將其解析為該引用的上一個提交。
可以使用 HEAD^ 來檢視上一個提交,也就是 “HEAD 的父提交”:

$ git show HEAD^

也可以在 ^ 後面新增一個數字——例如 d921970^2 代表 “d921970 的第二父提交”這個語法只適用於合併(merge)的提交,因為合併提交會有多個父提交。第一父提交是合併時所在分支,而第二父提交是所合併的分支。
另一種指明祖先提交的方法是 ~。同樣是指向第一父提交,因此 HEAD~ 和 HEAD^ 是等價的。而區別在於在後面加數字的時候。HEAD~2 代表 “第一父提交的第一父提交”,也就是 “祖父提交” —— Git 會根據指定的次
數獲取對應的第一父提交。

提交區間

最常用的指明提交區間語法是雙點。這種語法可以讓 Git 選出在一個分支中而不在另一個分支中的提交。例如,有如下的提交歷史
在這裡插入圖片描述
想要檢視 experiment 分支中還有哪些提交尚未被合併入 master 分支。可以使用 master…experiment
來讓 Git 顯示這些提交。也就是 “在 experiment 分支中而不在 master 分支中的提交”。示例:

$ git log master..experiment
D
C

反過來,如果你想檢視在 master 分支中而不在 experiment 分支中的提交,你只要交換分支名即
可。experiment…master 會顯示在 master 分支中而不在 experiment 分支中的提交:

$ git log experiment..master
F
E

"$ git log origin/master…HEAD"命令會輸出在你當前分支中而不在遠端 origin 中的提交。
Git 允許在任意引用前加上 ^ 字元或者 --not 來指明不希望提交被包含其中的分支。因此下列3個命令是等價的:

$ git log refA..refB
$ git log ^refA refB
$ git log refB --not refA

比如,你想檢視所有被refA 或 refB 包含的但是不被 refC 包含的提交,可以輸入下面中的任意一個命令

$ git log refA refB ^refC
$ git log refA refB --not refC

這個語法可以選擇出被兩個引用中的一個包含但又不被兩者同時包含的提交。

在這裡插入圖片描述
如果想看 master 或者 experiment 中包含的但不是兩者共有的提交,可以執行

$ git log master...experiment
F
E
D
C

這種情形下,log 命令的一個常用引數是 --left-right,它會顯示每個提交到底處於哪一側的分支。這會讓
輸出資料更加清晰。

$ git log --left-right master...experiment
< F
< E
> D
> C

互動式暫存

如果執行 git add 時使用 -i 或者 --interactive 選項,Git 將會進入一個互動式終端模式,顯示類似
下面的東西:

$ git add -i
           staged unstaged path
  1: unchanged +0/-1 TODO
  2: unchanged +1/-1 index.html
  3: unchanged +5/-1 lib/simplegit.rb
*** Commands ***
  1: status 2: update 3: revert 4: add untracked
  5: patch 6: diff 7: quit 8: help
What now>

這個命令以非常不同的檢視顯示了暫存區 - 基本上與 git status 是相同的資訊,但是更簡明扼要一些。它將暫存的修改列在左側,未暫存的修改列在右側。
在這塊區域後是命令區域。在這裡可以做一些工作,包括暫存檔案、取消暫存檔案、暫存檔案的一部分、新增未被追蹤的檔案、檢視暫存內容的區別。
如果在 What now> 提示符後鍵入 2 或 u,指令碼將會提示想要暫存哪個檔案。
每個檔案前面的 * 意味著選中的檔案將會被暫存。如果在 Update>> 提示符後不輸入任何東西並直接按回車,Git 將會暫存之前選擇的檔案。
如果這時想要取消暫存檔案,使用 3 或 r(撤消)選項。
如果想要檢視已暫存內容的區別,可以使用 6 或 d(區別)命令。
Git 也可以暫存檔案的特定部分。例如,如果在某一個檔案中做了兩處修改,但只想要暫存其中的一個而不是另一個,Git 會幫你輕鬆地完成。從互動式提示符中,輸入 5 或 p(補丁)。Git 會詢問你想要部分暫存哪些檔案;然後,對已選擇檔案的每一個部分,它都會一個個地顯示檔案區別並詢問你是否想要暫存它們。
也可以不必在互動式新增模式中做部分檔案暫存 - 可以在命令列中使用 git add -p 或 git add --patch 來啟動同樣的指令碼。
更進一步地,可以使用 reset --patch 命令的補丁模式來部分重置檔案,通過 checkout --patch 命令來部分檢出檔案與 stash save --patch 命令來部分暫存檔案。