首页 > 解决方案 > 为什么 Git 使用类似“origin foo”、“remotes/origin/foo”和“origin/foo”这样容易混淆的名称?

问题描述

我被要求使用 Fork 工作流程,即我必须处理具有相同或相似名称的多个分支。为什么我要使用这些不同的变体?

以下是不同命名约定的一些示例:

标签: gitgit-fork

解决方案


仔细背诵一系列记住的 Git 命令。Git 有一个简单但功能强大的对象模型。了解 git 命令如何根据对象模型工作,以及您想做的事情如何适应命令的作用。以我的经验,运行记忆的命令有时会导致多次重复调用,以挫败相同的顺序,这可能会以奇怪的方式纠缠历史。疑惑的队友过来求救​​后,我坐下,看了看现在的状态,挠了挠头,问道:“你怎么会变成这个状态?”

用于跟踪分支的命名方案(例如,origin/mybranchremotes/origin/mybranch—— 或什refs/remotes/origin/mybranch至和类似的 for upstream/mybranch)泄露了分支命名空间的实现细节,即。refs和是解压remotes,origin存储的物理目录。请参阅git pack-refs文档或深入了解下面的目录层次结构.git/refs

为方便用户,Git 接受分支的缩写名称,类似于用户无需输入完整的 40 个字符的 SHA1 对象名称。git rev-parse文档解释了。

<refname>, 例如master, heads/master,refs/heads/master
一个符号引用名称。例如master,通常表示 . 引用的提交对象refs/heads/master。如果你碰巧同时拥有 heads/masterand tags/master,你可以明确heads/master地告诉 Git 你指的是哪一个。当<refname>有歧义时,通过以下规则中的第一个匹配来消除 a 的歧义:

  1. 如果$GIT_DIR/<refname>存在,这就是你的意思(这通常只对HEAD, FETCH_HEAD, ORIG_HEAD,MERGE_HEAD和有用CHERRY_PICK_HEAD);

  2. 否则,refs/<refname>如果存在;

  3. 否则,refs/tags/<refname>如果存在;

  4. 否则,refs/heads/<refname>如果存在;

  5. 否则,refs/remotes/<refname>如果存在;

  6. 否则,refs/remotes/<refname>/HEAD如果它存在。

Git 文档将其refs/remotes/origin/foo称为符号全名完整 refname,它们对于按名称指定精确引用很有用,不会有歧义——例如在自动化程序中。

请注意,mybranch指的是您的本地 mybranch,而不是其跟踪分支(或远程跟踪分支)origin/mybranchupstream/mybranch. 每次抓取或拉取都会更新跟踪分支。将它们视为您历史记录中的书签,或者您上次拉动遥控器时沿路径的路标。有可能——并且经常发生这种情况——mybranchorigin/mybranch引用不同的提交。

相反origin mybranch,从不指代origin/mybranchmybranch。Git 没有“/ 操作符”。这种想法使这两个独立的论点脱离了上下文。请记住,Git 是一套命令行工具,命令行工具接受参数作为位置参数,而 Unix 命令 shell 通过空格分割参数。在上下文中,命令

git push origin master

有一般形式

git push <remote> <branch>

也就是说,一个参数命名一个远程,另一个命名一个(通常是本地的)分支。<branch>所以在英语中,它的意思是“将我的(在本例中命名)上的提交推master送到远程(origin在本例中命名)。”


推荐阅读