Git中的commit-ish和tree-ish是什么?

147

问题

Git中的commit-ish和tree-ish有哪些具体示例?

Stack Overflow上的问题“Git中的tree-ish是什么意思?”处理了tree-ish的具体含义,但我想更多地了解两者

背景

文档中的用法

Git文档中多次提到“commit-ish”和“tree-ish”。例如,如果您正在检查Git源代码

$ git grep --files-with-matches --extended-regexp "commit(-)*ish"
config.txt
git-describe.txt
git-fast-import.txt
git-name-rev.txt
git-push.txt
git-rebase.txt
git-rev-parse.txt
git.txt
gitcli.txt
glossary-content.txt
howto/revert-branch-rebase.txt
revisions.txt

$ git grep --files-with-matches --extended-regexp "tree(-)*ish" | \
$ grep --invert-match RelNotes
diff-format.txt
diff-generate-patch.txt
git-archive.txt
git-cat-file.txt
git-checkout.txt
git-diff-index.txt
git-diff-tree.txt
git-ls-files.txt
git-ls-tree.txt
git-merge-tree.txt
git-read-tree.txt
git-reset.txt
git-svn.txt
git.txt
gitcli.txt
gittutorial-2.txt
glossary-content.txt
revisions.txt

定义

Git文档定义了"commit-ish"和"tree-ish"的含义:

<tree>

表示树对象名称。

<commit>

表示一个提交对象的名称。

<tree-ish>
表示树、提交或标签对象名称。一个需要使用 <tree-ish> 参数的命令最终想要操作的是一个 <tree> 对象,但会自动取消引用指向 <tree><commit><tag> 对象。
<commit-ish>

表示提交或标签对象名称。需要一个<commit-ish>参数的命令最终希望操作一个<commit>对象,但会自动解引用指向<commit><tag>对象。


请参阅在线 git词汇表,或在您的CLI中使用 man gitglossary - iolsmit
2个回答

200

简短回答(TL;DR)

以下是完整的提交和树标识符列表(来自Git修订文档):

----------------------------------------------------------------------
|    Commit-ish/Tree-ish    |                Examples
----------------------------------------------------------------------
|  1. <sha1>                | dae86e1950b1277e545cee180551750029cfe735
|  2. <describeOutput>      | v1.7.4.2-679-g3bee7fb
|  3. <refname>             | master, heads/master, refs/heads/master
|  4. <refname>@{<date>}    | master@{yesterday}, HEAD@{5 minutes ago}
|  5. <refname>@{<n>}       | master@{1}
|  6. @{<n>}                | @{1}
|  7. @{-<n>}               | @{-1}
|  8. <refname>@{upstream}  | master@{upstream}, @{u}
|  9. <rev>^                | HEAD^, v1.5.1^0
| 10. <rev>~<n>             | master~3
| 11. <rev>^{<type>}        | v0.99.8^{commit}
| 12. <rev>^{}              | v0.99.8^{}
| 13. <rev>^{/<text>}       | HEAD^{/fix nasty bug}
| 14. :/<text>              | :/fix nasty bug
----------------------------------------------------------------------
|       Tree-ish only       |                Examples
----------------------------------------------------------------------
| 15. <rev>:<path>          | HEAD:README.txt, master:sub-directory/
----------------------------------------------------------------------
|         Tree-ish?         |                Examples
----------------------------------------------------------------------
| 16. :<n>:<path>           | :0:README, :README
----------------------------------------------------------------------

标识符#1-14都是“提交-是”,因为它们都指向提交,但是因为提交也指向目录树,所以它们最终都会指向(子)目录树对象,并且因此也可以用作“树状物”。
当#15引用(子)目录时,它也可以用作树形物,但是它还可以用于标识特定文件。当它引用文件时,我不确定它是否仍然被视为“树状物”,或者更像“blob-ish”(Git将文件称为“blob”)。
在Git中,提交和目录树的基本原理如下:
在其最低级别上,Git使用四个基本对象来跟踪源代码:
1.带注释的标签,指向提交。 2.提交,指向项目的根目录树。 3.目录和子目录。 4.文件。
每个对象都有自己的sha1哈希ID,因为Linus Torvalds将Git设计成类似于内容可寻址文件系统,即可以根据文件内容检索文件(sha1 ID是从文件内容生成的)。《Pro Git》书中给出了这个示例图表

Figure 9-3 from Pro Git book

Commit-ish与Tree-ish

许多Git命令可以接受特殊的标识符来表示提交和(子)目录树:

  • "Commit-ish"是最终指向提交对象的标识符。例如,

    tag -> commit

  • "Tree-ish"是最终指向树形(即目录)对象的标识符。

    tag -> commit -> project-root-directory

因为提交对象始终指向一个目录树对象(即您项目的根目录),所以任何“commit-ish”标识符都是“tree-ish”标识符。换句话说,任何导致提交对象的标识符也可以用来导致(子)目录树对象

但由于目录树对象在Git版本控制系统中从不指向提交,因此并非指向(子)目录树的每个标识符都可以用于指向提交。换句话说,“commit-ish”标识符集是“tree-ish”标识符集的严格子集。

不能用作提交标识符的树状标识符集合包括:

  1. <rev>:<path>,它直接指向目录树而不是提交对象。例如,HEAD:subdirectory

  2. 目录树对象的Sha1标识符。


4
不要忘记stash@{0}。我想知道它在这一切中的作用。还有其他像stash(my-thing@{0})这样的东西吗?stash只是一个<refname>吗? - Nate
1
尚未明确说明树形标识符似乎比提交标识符更具体。也许我很奇怪,但在我看来,这是唯一合理的解释方式。 - Steven Lu
所以<rev>是提交哈希的另一个同义词吗?还是完全不同的东西? - Jonah

49
非英语母语者请注意:“-ish”是一个后缀,可用于形容词中,表示“具有像...的品质”或“稍微”的意思 - 详见http://chambers.co.uk/search/?query=ish&title=21st 因此,“tree-ish”-像一棵“树”.... “commit-ish”-像一个“提交”
例如,“火星看起来像颗红色的星星”(“d”重复了!);“盘子里的食物不是热的,但是有点温暖”
我相信这有助于更好地解释“什么是...”,因为它解释了语言用法。

我一直将“tree-ish”和“commit-ish”解释为类似于说“瑞典语”或“英语”。你所描述的用法对我来说不太合理,因为这种“ish”形式创建了一个形容词。但是,rev并不是“像”树或提交,它就是树或提交。另一方面,如果你把“ish”看作是一种语言后缀,那么它们在命令行上作为名词更有意义,“tree-ish”是形成名词的语言。我不知道作者的意图是哪种解释,但这就是我一直以来的看法。 - jmt
3
我明白你的观点,但我只是想给出作为母语英语者的印象! - MikeW
我倾向于同意@MikeW的观点(尽管我是以法语为母语的);虽然从技术上讲,“commit-ish”应该是一个形容词,但我注意到你自己创造的术语往往会变成名词。几个月前,我经常使用“总线宽度”这个术语,最终我开始将其作为一个整体单词“buswidth”写下来,就好像它是一个名词一样,因为我对它非常熟悉。就像Linux的termios或法语表达式bon jour(“good day”),最终变成了bonjour。我实际上很惊讶他们仍然将其写成“commit-ish”,而不是“commitish”。 - adentinger
2
从形式上讲,“tree-ish”和“commit-ish”这样的形容词被用作名词,这是省略的一种形式;它们实际上意味着“类似树的东西”和“类似提交的东西”。也许对于非英语国家的人来说,“伪树”和“伪提交”这样的术语更为明显,类比于“伪代码”。 - Jivan Pal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接