简体中文 ▾ 主题 ▾ 最新版本 ▾ 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] 套件的一部分