.git / refs中的哪些目录有特殊含义?

时间:2017-11-09 17:27:53

标签: git

.git/refs中,The Git Book中描述了三个目录:

heads
remotes
tags

此外,git replace creates目录replace。所以至少这四个名字是已知的,对Git有特殊意义。

但是,例如自己的存储库中的Gerrit creates目录forchanges。 (这只是一个例子,我不会问任何关于Gerrit的事情。)例如,我可以获取'更改'refs。 Git会知道它们不是分支而不是远程 - 它们是否像标签一样处理?

Git一般如何理解.git/refs中的“非标准”内容?这样的用例可以是什么?除了上面列出的参考文献之外,还有其他“标准”目录吗?

2 个答案:

答案 0 :(得分:3)

我对此的看法与Schwern's answer略有不同:没有目录具有特殊含义。相反,某些前缀字符串具有含义。

Git关心的是引用,它们是以refs/开头的符合git check-ref-format强加的限制的名称。 Git有时会选择将这些名称存储为普通文件路径名,有时候不会将它们全部存储在一个简单的文本数据库文件中。.git/packed-refs将它们全部存储起来。将来,除了平面文件和/或目录树之外,Git可以使用真实数据库。如果您坚持使用已发布的界面(如下所述),您可以将自己与以后的任何格式更改隔离开来。

Git中定义的前缀字符串是(我试图使这个列表完整,但我忘了Schwern添加的至少一个,所以我添加了它:-)):

  • refs/bisect/:有关正在进行的二分法的信息
  • refs/heads/:分支机构名称
  • refs/notes/:注意名称
  • refs/original/git filter-branch使用它来存储所有原始(预过滤操作)参考
  • refs/remotes/:远程跟踪名称
  • refs/replace/:替换对象
  • refs/stash :(单数)藏匿
  • refs/tags/:标记名称

所有其他名称都可用,至少在某些第三方扩展程序被集成到Git中之前。

要编写参考,请使用the shell command git update-ref。这可以创建,更新或删除对任何有效散列ID的引用。要编写符号引用,请使用git symbolic-ref。两个命令都会更新引用的 reflog (如果存在),或者在适当时创建或删除它。

要浏览所有引用,请使用git for-each-ref。要在逻辑树结构中遍历特定引用,您可以继续使用git for-each-ref(它需要前缀和glob模式),或者使用一些更面向用户的命令(如git branch和{{1例如,对git tag使用--branches--tags和/或--remotes个参数。

如果要使用较低级别的操作,请注意,当前git rev-list --no-walk中存在的文件会覆盖存储在平面文件.git/refs文件中的任何值。我怀疑如果/当Git获得一个真正的参考数据库时,真数据库条目将覆盖所有其他数据库,并且可能存在数据库条目类型代码"此名称曾经存在,但现在不存在" 。 (如果数据库有效,它可能还会保存reflog条目,这将是一个允许"取消删除"旧引用的好方法。)

答案 1 :(得分:2)

  

Git如何理解.git / refs中的“非标准”内容?

没有。它忽略了它们。

.git是目录树。与任何其他目录树一样,文件和目录名称对git具有意义。 .git/refs/的每个顶级目录都具有git的特定含义。

  • .git/refs/heads/包含分支头(即master
  • .git/refs/tags/包含标签(即v1.2.3
  • .git/refs/remotes/包含远程分支头(即origin/master

Git命令将遍历这些目录中的文件,以发现可用的分支,标记和远程控制。并且它知道它何时需要,例如,它在.git/refs/tags/中看到的标签。

例如,git branch有效地列出了.git/refs/heads/及其子目录中的所有文件。 git tag -l执行.git/refs/tags/git branch -r执行.git/refs/remotes/。请注意,有"packed refs"这样的优化使得这不再那么简单了。

git中的任何其他内容都不会使用。就像你的主目录中的文件和目录被许多程序放在那里一样,它们每个人都只关心自己的程序。

  

这样的用例可以是什么?

你已经用Gerrit回答了你的问题。当第三方Git实用程序需要存储有关本地存储库的额外信息时,可以将它放在.git中。与在代码树顶部放置.gerrit目录不同,.git中的额外文件和目录被大多数其他实用程序忽略。如果您移动或复制repo目录,.git中的额外Gerrit信息将随之而来。

例如,当Gerrit想要存储其他类型的引用时,它可以将它们放在.git/refs/changes/.git/refs/for/中,而不会干扰正常的git功能。

  

除了我上面列出的那些之外,还有其他“标准”目录吗?

我怀疑是否有明确的清单,您可能需要扫描git的源代码。有关已知目录的列表,请参阅@torek's answer