Git中的树状含义是什么?


122

我对如何使用非常困惑git archive

我有一个git仓库,在顶层有FooBarBaz文件夹 。我需要以一种类似于SVN的方式导出文件夹Foo,以进行快速测试部署。

我才知道,我可以用git-archiveSVN-ISH出口排序的方式

但是,事情就这样了,以下工作正常:

git archive master | tar -x -C ~/destination

结果是目标文件夹中的FooBarBaz文件夹。

然而,下面就会因错误使用fatal not a valid object name

git archive master/foo | tar -x -C ~/destination

文档资料

看起来像是 git archive程序我看到它可以<tree-ish> [path]作为参数(提要总结到相关部分):

git archive <tree-ish> [path...]

如果 master/foo 不是 tree-ish,那是什么?


2
master:foo是树状的,但最好使用master fooi <tree-ish> <path>
JakubNarębski2010年

1
我已经将<tree-ish>解释为[path]的形容词。那是我做错的地方。而且我看到的所有示例仅使用命令的<tree-ish>部分,因此我错误地假定它们正在使用'<tree-ish>路径。哦,语义:)
dkinzer 2010年


3
我对这个问题有疑问,因为标题询问的是git中的树状内容,但随后它开始了,似乎主要是关于某些命令的。此外,公认的答案似乎并没有解决“树状”一词的确切含义。问题的标题必须更改,或者问题必须更改。我建议标题更适合问题的实际情况和可接受的答案。或者,可以将接受的答案更改为问题标题的真正含义。或答案应解决问题标题。
查理·帕克

@CharlieParker显然是手册的手册页git archive不再引用树状,但当我问这个问题时,他们确实引用了。关于已接受的答案;当时没有人愿意回答这个问题。两年多以后,甚至发布了另一个答案。
dkinzer 2014年

Answers:


166

简短答案(TL; DR)

“树状”是指最终导致(子)目录树(Git将目录称为“树”和“树对象”)的任何标识符(如Git修订版文档中所指定)。

在原始发布者的情况下,foo 他要指定的目录。在Git中指定(子)目录的正确方法是使用此“树状”语法(Git修订文档中的项目#15 ):

<rev>:<path>例如HEAD:README:READMEmaster:./README

在后缀:后跟路径的名称是树状对象中给定路径上的斑点或树的名称,该对象由冒号前的部分命名。

换句话说,master:foo正确的语法不是master/foo

其他“树状”(加上提交状)

这是提交和树状标识符的完整列表(来自Git修订版文档感谢LopSae指出):

----------------------------------------------------------------------
|    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, :README, master:./README
----------------------------------------------------------------------
|         Tree-ish?         |                Examples
----------------------------------------------------------------------
| 16. :<n>:<path>           | :0:README, :README
----------------------------------------------------------------------

标识符#1-14都是“ commit-ish”,因为它们都导致提交,但是由于提交也指向目录树,因此它们最终都导致(子)目录树对象,因此也可以用作“ tree” -ish”。

#15引用(子)目录时,还可以用作树状目录,但也可以用于标识特定文件。当它指向文件时,我不确定它是否仍被视为“树状”或行为更像“斑点状”(Git将文件称为“斑点”)。

长答案

在最低层次上,Git使用四个基本对象跟踪源代码:

  1. 带注释的标记,指向提交。
  2. 提交,指向项目的根目录树。
  3. 树,是目录和子目录。
  4. Blob,是文件。

这些对象中的每一个都有其自己的sha1哈希ID,因为Linus Torvalds将Git设计为可寻址内容的文件系统,即可以根据文件的内容来检索文件(sha1 ID是从文件内容生成的)。Pro Git书给出了以下示例图

Pro Git书中的图9-3

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

  • “提交”是最终导致提交对象的标识符。例如,

    tag -> commit

  • “树状”是最终导致树(即目录)对象的标识符。

    tag -> commit -> project-root-directory

因为提交对象总是指向目录树对象(项目的根目录),所以根据定义,任何“ commit-ish”标识符也就是“ tree-ish”。换句话说,任何导致提交对象的标识符也可以用于导致(子)目录树对象

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

文档所述感谢Trebor帮助我找到它):

<tree>

指示树对象名称。

<commit>

指示提交对象名称。

<tree-ish>

指示树,提交或标记对象名称。带有<tree-ish> 参数的命令最终希望对一个<tree>对象进行操作,但是会自动取消引用<commit><tag>指向的对象<tree>

<commit-ish>

指示提交或标记对象名称。带有<commit-ish> 参数的命令最终希望对一个<commit>对象进行操作,但会自动取消引用<tag>指向的对象<commit>

不能用作提交树的树形标识符的集合是

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

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


桌上的第16条呢?这是否意味着您不确定是否是树状?0表示合并状态,该概念仅适用于blob,因为索引甚至不包含目录。请参阅:stackoverflow.com/a/25806452/895245。那么问题就归结为:是否所有斑点现象也都是树状现象?据我所知,使用的所有手册页都<tree-ish>接受并man gitrevisions定义:trees ("directories of files")
Ciro Santilli郝海东冠状病六四事件法轮功

请注意,git-archive它说需要a,<tree-ish>但不允许a <sha1>。所以我想应该改为要求<tree-ish-ish>stackoverflow.com/a/12073669/680464
juanitogan 2014年

但是,我想知道使用<rev>时会发生什么:(没有任何路径?。它可以尝试运行-但是我在文档中找不到相关的部分。)
Martin Vejmelka,2015年

49

树状树是命名特定树的一种方式,可以是以下之一:

  • 引用如下:
    • 标签
    • 分行名称
    • 带有遥控器的分支名称,例如 origin/somebranch
  • 杂凑
  • 短哈希

最重要的是,以上任何内容都可以添加^~。引用也可以将@{}符号用于某些其他功能:

  • HEAD^HEAD^1将解析为HEAD的第一个父级。
  • HEAD^2 将解决第二个父母
  • HEAD^3将解析为第三个父级,依此类推,这种情况较为罕见,并且是与章鱼策略合并的产物 。
  • HEAD~HEAD~1将解析为head的第一个父项
  • HEAD~2将解析为HEAD的第一个父级的第一个父级。这将与HEAD^^
  • HEAD@{0} 将解析为当前的HEAD
  • HEAD@{1}将解析为前一个头。这只能由参考使用,因为它利用了参考日志。对于HEAD每次提交,合并,签出都会更改HEAD的值,并将其添加到日志中。git reflog HEAD将显示参考日志,您可以在其中查看HEAD的所有运动,并正确地@{1}解决了诸如此类的问题。

上述大部分可以进一步结合,只要它是有道理的在你的仓库,例如:HEAD@{2}~3somebranch^2~4c00e66e~4^2anotherbranch~^~^~^

因此,上述任何内容及其组合,在文档中都以树状表示,这只是一种方式,它说明什么树(或修订版)是大多数git命令都应使用的树。

有关更多信息,请参见Git书中的“版本选择”


1
该答案通常解释了修订(提交),master:path/to/directory而没有想到以下关键情况:,是树状但不是提交状。纸杯蛋糕使这一点变得更加清晰。
西罗Santilli郝海东冠状病六四事件法轮功

11

你可能想要

git archive master foo | tar -x -C ~/destination

该表达式master/foo没有意义:master是分支名称,并且foo我认为目录名称。

编辑:(已删除断开的链接。请参阅注释。)


在“ Git Treeishes”链接上不再找到“ tree”一词。仅供参考
罗伯特

树状结构通常是指修订树,而不是目录布局。
尔根·斯特罗贝尔

6
@JürgenStrobel:事实并非如此。由于过去时,它没有提到这两个词,因为在当前版本的文档中不再使用该词。(这也是链接断开的原因。)以前,树状结构指的是可以解析为git对象存储中的树状对象的事物。这包括任何提交规范,因为每个提交都引用单个树对象。树对象包含有关此提交的目录树的信息–有关详细信息,请参见“ Pro Git”中有关git对象部分
Sven Marnach 2012年

6

对于定义<tree-ish><commit-ish>看到的git(1)手册页。您必须搜索条款。通常,它<tree-ish>是指对git树对象的引用,但是如果您传递引用树的对象类型(例如,提交或分支),则git将自动使用引用的树。


gitrevisions(7)
熊加米奥夫

0

我是源代码控制和git的新手。这就是我所知道的。树是存储库中文件的结构。它类似于文件系统中的目录。请参阅- 哪个git工具生成了此树形视图?

树状意味着像一棵树。它引用树的一部分或提交。您可以使用以下任意一种引用提交:提交的SHA-1散列的全部或一部分,HEAD指针,分支引用,标签引用。另一种方法将上述方法中的任何一种与提交的祖先或父母一起使用。祖先的例子: 在此处输入图片说明


0

Git词汇表来看,树状含义是“树对象或可以递归引用到树对象的对象”。commit,HEAD和tag是树状对象的示例。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.