簡體中文 ▾ 主題 ▾ 最新版本 ▾ gitrevisions 上次更新於 2.42.0

名稱

gitrevisions - 為 Git 指定修訂和範圍

概要

gitrevisions

描述

許多 Git 命令以引數形式接受修訂引數。根據命令的不同,它們可能表示一個特定的提交,或者對於遍歷修訂圖(如 git-log[1])的命令,則表示從該提交可達的所有提交。對於遍歷修訂圖的命令,還可以顯式指定修訂範圍。

此外,一些 Git 命令(如 git-show[1]git-push[1])還可以接受表示提交以外的其他物件的修訂引數,例如 blob(“檔案”)或 tree(“檔案目錄”)。

指定修訂

修訂引數 <rev> 通常(但不一定)命名一個提交物件。它使用所謂的 擴充套件 SHA-1 語法。以下是拼寫物件名稱的各種方法。列表中接近末尾的那些表示提交中包含的 tree 和 blob。

注意
本文件顯示的是 Git 看到的“原始”語法。shell 和其他 UI 可能需要額外的引號來保護特殊字元並避免單詞分割。
<sha1>,例如 dae86e1950b1277e545cee180551750029cfe735dae86e

完整的 SHA-1 物件名稱(40 位元組十六進位制字串),或在儲存庫中唯一的開頭子串。例如,如果您的儲存庫中沒有其他物件名稱以 dae86e 開頭,則 dae86e1950b1277e545cee180551750029cfe735 和 dae86e 都指向同一個提交物件。

<describeOutput>,例如 v1.7.4.2-679-g3bee7fb

來自 git describe 的輸出;即,最近的標籤,後跟一個破折號和一個提交數,再後跟一個破折號、一個 g 和一個縮寫的物件名稱。

<refname>,例如 master, heads/master, refs/heads/master

符號引用名稱。例如,master 通常表示 refs/heads/master 引用的提交物件。如果您同時擁有 heads/mastertags/master,則可以明確指定 heads/master 來告知 Git 您指的是哪一個。當存在歧義時,將按照以下規則的順序匹配來消歧 <refname>

  1. 如果 $GIT_DIR/<refname> 存在,則表示您指的是該引用(這通常僅對 HEAD, FETCH_HEAD, ORIG_HEAD, MERGE_HEAD, REBASE_HEAD, REVERT_HEAD, CHERRY_PICK_HEAD, BISECT_HEADAUTO_MERGE 有用);

  2. 否則,如果 refs/<refname> 存在;

  3. 否則,如果 refs/tags/<refname> 存在;

  4. 否則,如果 refs/heads/<refname> 存在;

  5. 否則,如果 refs/remotes/<refname> 存在;

  6. 否則,如果 refs/remotes/<refname>/HEAD 存在。

    HEAD

    指向您基於工作樹中的更改的提交。

    FETCH_HEAD

    記錄了您上次呼叫 git fetch 時從遠端儲存庫拉取的遠端分支。

    ORIG_HEAD

    由那些會劇烈移動您的 HEAD 的命令(如 git am, git merge, git rebase, git reset)建立,用於記錄操作前 HEAD 的位置,以便您可以輕鬆地將分支尖端改回它們執行之前的狀態。

    MERGE_HEAD

    在您執行 git merge 時,記錄了您正在合併到當前分支的提交(或提交列表)。

    REBASE_HEAD

    在 rebase 過程中,記錄了操作當前停止的提交,可能是因為衝突,也可能是因為互動式 rebase 中的 edit 命令。

    REVERT_HEAD

    在您執行 git revert 時,記錄了您正在 revert 的提交。

    CHERRY_PICK_HEAD

    在您執行 git cherry-pick 時,記錄了您正在 cherry-pick 的提交。

    BISECT_HEAD

    在您執行 git bisect --no-checkout 時,記錄了當前要測試的提交。

    AUTO_MERGE

    記錄了在 merge 操作導致衝突時,ort 合併策略寫入工作樹的樹物件。

請注意,上面任何 refs/* 的情況都可能來自 $GIT_DIR/refs 目錄,也可能來自 $GIT_DIR/packed-refs 檔案。雖然引用名稱的編碼未指定,但優先使用 UTF-8,因為某些輸出處理可能會假定引用名稱是 UTF-8 編碼的。

@

單獨的 @HEAD 的快捷方式。

[<refname>]@{<date>},例如 master@{yesterday}, HEAD@{5 minutes ago}

一個引用後面跟著一個 @ 符號,後跟一對大括號括起來的日期規範(例如 {yesterday}{1 month 2 weeks 3 days 1 hour 1 second ago}{1979-02-26 18:30:00}),表示該引用在過去某個時間點的值。此後綴只能緊跟在引用名稱後面,並且該引用必須具有現有的日誌($GIT_DIR/logs/<ref>)。請注意,這會查詢您 **本地** 引用的給定時間的狀態;例如,上週您的本地 master 分支是什麼樣的。如果您想檢視在特定時間內進行的提交,請參閱 --since--until

<refname>@{<n>},例如 master@{1}

一個引用後面跟著一個 @ 符號,後跟一對大括號括起來的序數規範(例如 {1}{15}),表示該引用的第 n 個先前值。例如,master@{1}master 的前一個值,而 master@{5}master 的第 5 個先前值。此後綴只能緊跟在引用名稱後面,並且該引用必須具有現有的日誌($GIT_DIR/logs/<refname>)。

@{<n>},例如 @{1}

您可以使用 @ 結構,省略引用部分,以訪問當前分支的 reflog 條目。例如,如果您在 blabla 分支上,那麼 @{1}blabla@{1} 的意思相同。

@{-<n>},例如 @{-1}

構造 @{-<n>} 表示您在當前提交之前簽出的第 <n> 個分支/提交。

[<branchname>]@{upstream},例如 master@{upstream}, @{u}

一個分支 B 可以設定為構建在遠端 R(透過 branch.<name>.remote 配置)上的分支 X(透過 branch.<name>.merge 配置)之上。B@{u} 指的是來自遠端 R 的分支 X 的遠端跟蹤分支,通常位於 refs/remotes/R/X

[<branchname>]@{push},例如 master@{push}, @{push}

字尾 @{push} 報告當簽出 branchname(如果未指定 branchname,則為當前 HEAD)時,執行 git push 會推送到哪個分支。與 @{upstream} 類似,我們報告對應於遠端分支的遠端跟蹤分支。

這裡有一個例子來說明這一點:

$ git config push.default current
$ git config remote.pushdefault myfork
$ git switch -c mybranch origin/master

$ git rev-parse --symbolic-full-name @{upstream}
refs/remotes/origin/master

$ git rev-parse --symbolic-full-name @{push}
refs/remotes/myfork/mybranch

請注意,示例中我們設定了一個三角工作流,即從一個位置拉取,然後推送到另一個位置。在非三角工作流中,@{push}@{upstream} 相同,並且不需要它。

這個字尾也可以寫成大寫形式,意思與小寫形式相同,不區分大小寫。

<rev>^[<n>],例如 HEAD^, v1.5.1^0

修訂引數的字尾 ^ 表示該提交物件的第一個父提交。^<n> 表示第 <n> 個父提交(即 <rev>^ 等同於 <rev>^1)。作為特殊規則,<rev>^0 表示提交本身,當 <rev> 是指向提交物件的標籤物件名稱時使用。

<rev>~[<n>],例如 HEAD~, master~3

修訂引數的字尾 ~ 表示該提交物件的第一個父提交。修訂引數的字尾 ~<n> 表示該命名提交物件的第 <n> 代祖先提交,僅沿第一個父提交方向追溯。也就是說,<rev>~3 等同於 <rev>^^^,也等同於 <rev>^1^1^1。下面將透過圖示說明此形式的用法。

<rev>^{<type>},例如 v0.99.8^{commit}

字尾 ^ 後跟一個用大括號括起來的物件型別名稱,表示遞迴地解引用 <rev> 中的物件,直到找到 <type> 型別的物件,或者物件無法再解引用(在這種情況下,會報錯)。例如,如果 <rev> 是一個 commit-ish,<rev>^{commit} 表示相應的提交物件。類似地,如果 <rev> 是一個 tree-ish,<rev>^{tree} 表示相應的樹物件。<rev>^0<rev>^{commit} 的簡寫。

<rev>^{object} 可用於確保 <rev> 指向一個存在的物件,而無需要求 <rev> 是一個標籤,並且不解引用 <rev>;因為標籤本身就是一個物件,所以它不需要被解引用一次就可以得到一個物件。

<rev>^{tag} 可用於確保 <rev> 識別一個存在的標籤物件。

<rev>^{},例如 v0.99.8^{}

字尾 ^ 後跟一個空大括號對,表示該物件可能是一個標籤,會遞迴地解引用該標籤,直到找到一個非標籤物件。

<rev>^{/<text>},例如 HEAD^{/fix nasty bug}

修訂引數的字尾 ^,後跟一個包含以斜槓開頭的文字的大括號對,其功能與下面的 :/fix nasty bug 語法相同,只是它返回 ^ 前的 <rev> 可達的、最近的匹配提交。

:/<text>,例如 :/fix nasty bug

一個冒號,後跟一個斜槓,再後跟文字,表示一個提交物件的提交資訊匹配指定的正則表示式。此名稱返回任何引用(包括 HEAD)可達的、最近的匹配提交。正則表示式可以匹配提交資訊的任何部分。要匹配以字串開頭的訊息,可以使用例如 :/^foo。特殊序列 :/! 保留用於匹配的修飾符。:/!-foo 執行負匹配,而 :/!!foo 匹配字面上的 ! 字元,後跟 foo。任何以 :/! 開頭的其他序列目前都保留作他用。根據給定的文字,shell 的單詞分割規則可能需要額外的引用。

<rev>:<path>,例如 HEAD:README, master:./README

字尾 : 後跟路徑,表示冒號之前部分命名的 tree-ish 物件中,給定路徑下的 blob 或 tree。以 ./../ 開頭的路徑相對於當前工作目錄。給定的路徑將被轉換為相對於工作樹根目錄。這在引用具有與工作樹相同樹結構的提交或樹時,最適合用於定址 blob 或 tree。

:[<n>:]<path>,例如 :0:README, :README

一個冒號,可選地後跟一個階段編號(0 到 3)和一個冒號,再後跟路徑,表示索引中給定路徑下的 blob 物件。省略階段編號(及其後面的冒號)表示階段 0 條目。在合併期間,階段 1 是共同祖先,階段 2 是目標分支的版本(通常是當前分支),階段 3 是正在合併的分支的版本。

這是 Jon Loeliger 的一個圖示。提交節點 B 和 C 都是提交節點 A 的父提交。父提交按從左到右的順序排列。

G   H   I   J
 \ /     \ /
  D   E   F
   \  |  / \
    \ | /   |
     \|/    |
      B     C
       \   /
        \ /
         A
A =      = A^0
B = A^   = A^1     = A~1
C =      = A^2
D = A^^  = A^1^1   = A~2
E = B^2  = A^^2
F = B^3  = A^^3
G = A^^^ = A^1^1^1 = A~3
H = D^2  = B^^2    = A^^^2  = A~2^2
I = F^   = B^3^    = A^^3^
J = F^2  = B^3^2   = A^^3^2

指定範圍

git log 這樣的歷史遍歷命令操作的是一組提交,而不僅僅是一個提交。

對於這些命令,指定單個修訂,使用上一節中描述的符號,表示從給定提交可達的提交集。

指定多個修訂表示從任何給定提交可達的提交集。

一個提交的可達集包括提交本身及其祖先鏈中的提交。

有幾種符號可以指定一組連線的提交(稱為“修訂範圍”),如下所示。

提交排除

^<rev>(插入符號)符號

要排除從某個提交可達的提交,使用字首 ^ 符號。例如,^r1 r2 表示從 r2 可達的提交,但排除從 r1 可達的提交(即 r1 及其祖先)。

點號範圍符號

..(兩點)範圍符號

^r1 r2 集合操作非常常見,因此有一個簡寫形式。當您有兩個提交 r1r2(根據 SPECIFYING REVISIONS 中解釋的語法命名)時,您可以透過 ^r1 r2 來請求從 r2 可達但排除從 r1 可達的提交,並可以寫成 r1..r2

...(三點)對稱差符號

一個類似的符號 r1...r2 稱為 r1r2 的對稱差,定義為 r1 r2 --not $(git merge-base --all r1 r2)。它是從 r1(左側)或 r2(右側)可達但從兩者都不可達的提交集合。

在這兩種簡寫符號中,您可以省略一端,讓它預設為 HEAD。例如,origin..origin..HEAD 的簡寫,詢問“自從我從 origin 分支分叉以來,我做了什麼?” 類似地,..originHEAD..origin 的簡寫,詢問“自從我從 origin 分叉以來,origin 做了什麼?” 請注意,.. 將意味著 HEAD..HEAD,這是一個空範圍,既可達又不可達 HEAD。

專門設計用於接受兩個不同範圍的命令(例如,“git range-diff R1 R2”用於比較兩個範圍)確實存在,但它們是例外。除非另有說明,所有操作提交集的“git”命令都使用單個修訂範圍。換句話說,將兩個“兩點範圍符號”並列寫,例如

$ git log A..B C..D

對於大多數命令,**不**指定兩個修訂範圍。相反,它將命名一個單一的連線提交集,即那些可達自 B 或 D,但不可達自 A 或 C 的提交。在一個線性的歷史中,例如

---A---B---o---o---C---D

因為 A 和 B 可達自 C,所以這兩個點號範圍指定的修訂範圍是一個單一的提交 D。

其他 <rev>^ 父提交簡寫符號

另外三種簡寫形式,尤其適用於合併提交,用於命名由一個提交及其父提交組成的集合。

r1^@ 符號表示 r1 的所有父提交。

r1^! 符號包含提交 r1,但排除其所有父提交。單獨使用時,此符號表示單個提交 r1

<rev>^-[<n>] 符號包含 <rev> 但排除第 <n> 個父提交(即 <rev>^<n>..<rev> 的簡寫),其中 <n> 為 1(如果未給出)。這對於合併提交特別有用,您可以直接使用 <commit>^- 來獲取合併提交 <commit> 中合併的分支的所有提交(包括 <commit> 本身)。

雖然 <rev>^<n> 是關於指定單個父提交,但這三種符號也考慮其父提交。例如,您可以說 HEAD^2^@,但不能說 HEAD^@^2

修訂範圍摘要

<rev>

包含從 <rev> 可達的提交(即 <rev> 及其祖先)。

^<rev>

排除從 <rev> 可達的提交(即 <rev> 及其祖先)。

<rev1>..<rev2>

包含從 <rev2> 可達但排除從 <rev1> 可達的提交。當省略 <rev1> 或 <rev2> 時,預設值為 HEAD

<rev1>...<rev2>

包含從 <rev1> 或 <rev2> 可達但排除從兩者都可達的提交。當省略 <rev1> 或 <rev2> 時,預設值為 HEAD

<rev>^@,例如 HEAD^@

字尾 ^ 後跟一個 at 符號,與列出 <rev> 的所有父提交相同(意味著,包含其父提交可達的任何內容,但不包括提交本身)。

<rev>^!,例如 HEAD^!

字尾 ^ 後跟一個感嘆號,與給出提交 <rev> 及其所有父提交,並以 ^ 作為字首排除它們(及其祖先)的效果相同。

<rev>^-<n>,例如 HEAD^-, HEAD^-2

等同於 <rev>^<n>..<rev>,其中 <n> = 1(如果未給出)。

這裡有幾個例子,使用上面 Loeliger 的圖示,其中每個符號的擴充套件和選擇步驟都已仔細說明:

   Args   Expanded arguments    Selected commits
   D                            G H D
   D F                          G H I J D F
   ^G D                         H D
   ^D B                         E I J F B
   ^D B C                       E I J F B C
   C                            I J F C
   B..C   = ^B C                C
   B...C  = B ^F C              G H D E B C
   B^-    = B^..B
	  = ^B^1 B              E I J F B
   C^@    = C^1
	  = F                   I J F
   B^@    = B^1 B^2 B^3
	  = D E F               D G H E F I J
   C^!    = C ^C^@
	  = C ^C^1
	  = C ^F                C
   B^!    = B ^B^@
	  = B ^B^1 ^B^2 ^B^3
	  = B ^D ^E ^F          B
   F^! D  = F ^I ^J D           G H D F

另請參閱

GIT

Git[1] 套件的一部分