简而言之,git refs 的不同"部分"商定的标准条款是什么?
假设某个分支refs/heads/myBranches/subBranch
,应该做什么
refs/heads/myBranches/subBranch
heads/myBranches/subBranch
heads
myBranches/subBranch
名叫?
在托雷克的回答和再次重读文档之后,我会说
refs/heads/myBranches/subBranch
-完全限定的 ref(以避免与HEAD
等SPECIAL
名称混淆(。甚至可能只是为了简洁起见full ref
。heads/myBranches/subBranch
- ?,尽管 gitrevisionsotherwise, refs/remotes/<refname> if it exists;
认为它是refname
的(或者它仅适用于 refs/remote?或者,也许我只是想在没有意义的情况下阅读额外的含义,是吗?heads
-命名空间myBranches/subBranch
-参考名称
那么,我这样称呼它们是否正确,类似heads/myBranches/subBranch
的"ref"应该叫什么样子?
如果需要,可以提供一些上下文。
我们使用 Azure DevOps 服务(和 TFS(的 .NET 客户端库进行大量工作,遗憾的是,分支名称的表示方式/应传递方式并不总是足够一致。
分支名称可以是 API DTO/参数中的refs/heads/branch
、heads/branch
和branch
。
因此,为了避免许多明显的错误,我们将以下类用作防腐层的一部分。不过,对于我们使用的术语可能有点不标准,我并不完全满意。
public class GitRefString : IEquatable<GitRefString>
{
public static class Types
{
public const string Head = "head";
public const string Tags = "tags";
}
public static GitRefString Head(string name)
{
return new GitRefString(Types.Head, name);
}
public GitRefString(string type, string name)
{
Type = type;
Name = name;
}
public string Type { get; }
public string Name { get; }
public string Ref => $"refs/{Type}/{Name}";
...
}
您可能需要根据自己的目的发明自己的术语。
在内部,Git 调用所有这些东西(refs/*
(引用或引用。 还有特殊的引用名称HEAD
、ORIG_HEAD
、MERGE_HEAD
、CHERRY_PICK_HEAD
等。 这些是否算作"refs"有点值得怀疑,但 gitglossary 说 ref 是:
以
refs/
开头的名称(例如refs/heads/master
(,指向对象名称或其他引用(后者称为符号引用(。...有一些特殊用途的参考不以
refs/
开头。最值得注意的例子是HEAD
.
所以我也会称这些引用,但在内部,这些有时被称为伪引用。
引用分为命名空间,refs/heads/
下的引用是分支名称或头。refs/tags/
下的那些是标签名称。refs/remotes/
下的人是远程跟踪名称。 (Git 称它们为远程跟踪分支名称,甚至只是远程跟踪分支,但这样做可能会将它们与实际分支名称混为一谈,所以我更喜欢术语远程跟踪名称。每个远程数据库都有自己单独的远程跟踪命名空间:refs/remotes/origin/
列出从origin
复制的名称,而refs/remotes/fred/
列出从fred
复制的名称。
请注意,某些引用是按工作树的。 gitglossary声称只有HEAD
和refs/bisect/
名称是每个工作树的,但这显然是错误的:源代码实际上测试了三个refs/
空间。 幸运的是,这些用例很少见,您可能完全避免考虑它们。
如果您希望编写完全限定 ref 的代码(例如,根据需要将master
转换为refs/heads/master
(,并希望以与 Git 相同的方式执行此操作,则官方规则在 gitrevisions 文档中列为六步过程:
- 如果
$GIT_DIR/<refname>
存在,那就是你的意思(这通常只对HEAD
、FETCH_HEAD
、ORIG_HEAD
、MERGE_HEAD
和CHERRY_PICK_HEAD
有用(; - 否则,
refs/<refname>
如果存在; - 否则,
refs/tags/<refname>
如果存在; - 否则,
refs/heads/<refname>
是否存在; - 否则,
refs/remotes/<refname>
如果存在; - 否则,
refs/remotes/<refname>/HEAD
如果存在。
不幸的是,这过于简单化了:例如,当您使用git checkout
时,即使存在其他相同的标签名称,该名称也会首先尝试作为refs/heads/
分支名称。 因此,当foo
既是分支名称又是标记名称时,git checkout foo
会获得与git show foo
显示的提交不同的提交。
(这也未能涵盖每个工作树名称解析,该解析并不完全使用上述规则。
以编程方式,最好的办法可能是在除一个或几个例程之外的所有例程中要求使用完全限定的名称。 这些特殊例程是将不太限定的名称(例如,对于不明确foo
的情况,heads/foo
或tags/foo
(更改为完全限定名称的例程。 在这里你可以说:首选分支或标签作为一个选项,这样你就可以通过说你更喜欢标签来处理"面向标签"的命令,通过说你更喜欢分支来处理"面向分支"的命令。 (而且,如果你需要担心每个工作树的引用,你可能正在做一些你不应该做的事情。 😀