简体中文 ▾ 主题 ▾ 最新版本 ▾ gitrevisions 最后更新于 2.42.0

名称

gitrevisions - 为 Git 指定修订版本和范围

概要

gitrevisions

描述

许多 Git 命令接受修订版本参数。根据命令的不同,它们可以表示一个特定的提交,或者对于遍历修订版本图的命令(如 git-log[1]),表示从该提交可达的所有提交。对于遍历修订版本图的命令,还可以显式指定修订版本范围。

此外,一些 Git 命令(如 git-show[1]git-push[1])也可以接受代表除提交以外的其他对象(例如数据对象 "blob" 或树对象 "tree")的修订版本参数。

指定修订版本

修订版本参数 <rev> 通常(但非必须)指向一个提交对象。它使用所谓的“扩展 SHA-1”语法。以下是拼写对象名称的各种方式。列表末尾列出的方式用于命名提交中包含的树对象和数据对象。

注意
本文档显示的是 git 所识别的“原始”语法。Shell 和其他用户界面可能需要额外的引号来保护特殊字符并避免单词拆分。
<sha1>,例如 dae86e1950b1277e545cee180551750029cfe735dae86e

完整的 SHA-1 对象名称(40 字节十六进制字符串),或在仓库中唯一的起始子串。例如,如果没有其他对象的名称以 dae86e 开头,则 dae86e1950b1277e545cee180551750029cfe735 和 dae86e 都指向同一个提交对象。

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

git describe 的输出;即最近的标签,后跟可选的连字符和提交次数,再后跟连字符、字母 g 和简短的对象名称。

<refname>,例如 masterheads/masterrefs/heads/master

符号引用名。例如 master 通常指 refs/heads/master 所引用的提交对象。如果你恰好同时拥有 heads/mastertags/master,你可以显式写出 heads/master 来告诉 Git 你的意图。当存在歧义时,Git 会根据以下规则找到第一个匹配项来消除歧义:

  1. 如果 $GIT_DIR/<refname> 存在,即为你所指(这通常仅对 HEADFETCH_HEADORIG_HEADMERGE_HEADREBASE_HEADREVERT_HEADCHERRY_PICK_HEADBISECT_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 amgit mergegit rebasegit reset)创建,用于记录操作前的 HEAD 位置,以便你可以轻松地将分支顶端恢复到运行这些命令之前的状态。

    MERGE_HEAD

    记录当你运行 git merge 时正在合并到当前分支中的提交。

    REBASE_HEAD

    在变基(rebase)期间,记录操作当前停止位置的提交,原因可能是冲突或交互式变基中的 edit 命令。

    REVERT_HEAD

    记录当你运行 git revert 时正在撤销的提交。

    CHERRY_PICK_HEAD

    记录当你运行 git cherry-pick 时正在挑选的提交。

    BISECT_HEAD

    记录当你运行 git bisect --no-checkout 时当前要测试的提交。

    AUTO_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(如果未指定分支名称,则为当前 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:READMEmaster:./README

后缀 : 后跟路径,命名冒号前部分命名的 tree-ish 对象中给定路径下的数据对象或树对象。以 ./../ 开头的路径相对于当前工作目录。给定的路径将被转换为相对于工作树根目录的路径。这对于寻址与工作树具有相同树结构的提交或树中的数据对象或树对象最为有用。

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

冒号,可选地后跟暂存级编号(0 到 3)和冒号,再后跟路径,命名索引中给定路径下的数据对象。缺失暂存级编号(及随后的冒号)表示第 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(根据上文“指定修订版本”中的语法命名)时,你可以通过 ^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 到达,也可以从 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] 套件的一部分