树在Git中意味着什么?

dki*_*zer 111 git git-archive

我对如何使用感到很困惑git archive.

我有一个git存储库,顶层有文件夹 Foo,BarBaz.我需要以SVN方式导出文件夹Foo,以便快速进行测试部署.

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

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

git archive master | tar -x -C ~/destination
Run Code Online (Sandbox Code Playgroud)

它导致目标文件夹中的Foo,Bar,Baz文件夹.

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

git archive master/foo | tar -x -C ~/destination
Run Code Online (Sandbox Code Playgroud)

文档

作为该git archive程序的概要,我看到它可以<tree-ish> [path]作为一个参数(概要总结为相关部分):

git archive <tree-ish> [path...]
Run Code Online (Sandbox Code Playgroud)

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

小智 154

简答(TL; DR)

"Tree-ish"是指任何标识符(在Git修订文档中指定)最终导致(子)目录树(Git将目录称为"树"和"树对象")的术语.

在原始海报的情况下,foo 他想要指定的目录.在Git中指定(子)目录的正确方法是使用这种"tree-ish"语法(Git版本文档中的第15项):

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

:后跟路径的后缀命名在冒号前面的部分命名的树形对象中给定路径上的blob或树.

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

其他"Tree-ish"(Plus Commit-ish)

这里是commit-ish和tree-ish标识符的完整列表(来自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
----------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

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

#15在引用(子)目录时也可以用作树,但它也可以用于标识特定文件.当它引用文件时,我不确定它是否仍然被认为是"tree-ish",或者是否更像"blob-ish"(Git将文件称为"blob").

答案很长

在最低级别,Git使用四个基本对象跟踪源代码:

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

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

Pro Git图9-3

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

  • "Commit-ish"是最终导致提交对象的标识符.例如,

    tag -> commit

  • "Tree-ish"是最终导致树(即目录)对象的标识符.

    tag -> commit -> project-root-directory

由于提交对象始终指向目录树对象(项目的根目录),因此根据定义,任何"commit-ish"标识符也是"tree-ish".换句话说,任何指向提交对象的标识符也可用于指向(子)目录树对象.

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

正如文档中所解释的那样(感谢Trebor帮助我找到它):

<tree>
Run Code Online (Sandbox Code Playgroud)

表示树对象名称.

<commit>
Run Code Online (Sandbox Code Playgroud)

表示提交对象名称.

<tree-ish>
Run Code Online (Sandbox Code Playgroud)

表示树,提交或标记对象名称.采用一个的命令<tree-ish> 参数最终想要一个上操作<tree>对象,但自动取消引用<commit><tag>指向在对象<tree>.

<commit-ish>
Run Code Online (Sandbox Code Playgroud)

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

该集树十岁上下的标识符是为提交十岁上下不能使用

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

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


Lop*_*Sae 48

tree-ish是一种命名特定树的方法,可以是以下之一:

  • 参考文献如:
    • 标签
    • 分支名称
    • 分支名称与遥控器,如 origin/somebranch
  • 哈希
  • 短暂的哈希

最重要的是,上面的任何一个都可以附加^,~.引用还可以使用@{}符号来表示一些其他功能:

  • HEAD^或者HEAD^1将被解决为HEAD的第一位父母.
  • HEAD^2 将解析为第二个父母
  • HEAD^3将解决第三个父母等等,这是更罕见的与章鱼策略合并的产物 .
  • HEAD~HEAD~1将解决头部的第一个父母
  • HEAD~2将解析为HEAD的第一个父级的第一个父级.这将是相同的HEAD^^
  • HEAD@{0} 将解决当前的HEAD
  • HEAD@{1}将解决前一个头.这只能由引用使用,因为它使用了引用日志.在HEAD每次提交,合并,checkout 的情况下,将更改HEAD的值,从而将其添加到日志中.git reflog HEAD将显示参考日志,您可以在其中查看HEAD的所有动作以及正确@{1}解决的内容等.

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

因此,上面描述的任何内容及其组合都是文档中的树形,这只是一种说明应该用于大多数git命令的树(或修订版)的方法.

更多信息在Git书中的修订版选择中.

  • 这个答案大体上解释了修订(commit-ishes),但忽略了关键情况:`master:path/to/directory`,它是一个树形但不是一个 commit-ish。纸杯蛋糕让这更清楚。 (2认同)

Sve*_*ach 11

你可能想要

git archive master foo | tar -x -C ~/destination
Run Code Online (Sandbox Code Playgroud)

表达master/foo没有意义:master是一个分支名称,foo是一个目录名称,正如我所设想的那样.

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

  • @JürgenStrobel:那不是真的.它提到了两者中的任何一个 - 过去时,因为在当前版本的文档中不再使用该术语.(这也是链接断开的原因.)以前,*treeish*指的是可以解析为git对象存储中的树对象的东西.这包括任何提交规范,因为每个提交引用单个树对象.树对象包含有关此提交的目录树的信息 - 请参阅[Pro Git中的[git对象]部分](http://git-scm.com/book/en/Git-Internals-Git-Objects)细节. (6认同)

Tre*_*ude 5

有关git(1)手册页的定义<tree-ish><commit-ish>参见.您必须搜索这些条款.通常意味着对git树对象的引用,但是如果传递一种引用树的对象(例如提交或分支),git将自动使用引用的树.<tree-ish>