【问题标题】:What determines default branch after "git clone"?什么决定了“git clone”之后的默认分支?
【发布时间】:2021-02-25 17:54:52
【问题描述】:

我的理解是,克隆存储库的默认分支是被克隆的存储库中 HEAD 指向的任何分支。

我现在遇到了一个不正确的案例。我的理解显然是有缺陷的,那么在克隆(裸)repo 时,是什么决定了默认的 checkout 分支?

该 repo 上的最后一次提交是在裸 repo 的 HEAD 中引用的分支与我作为克隆中的 checkout 分支获得的分支之间的合并。

运行git remote show origin 返回:

Fetch URL: ...
Push  URL: ...
HEAD branch (remote HEAD is ambiguous, may be one of the following):
  <bad-branch>
  live
Remote branches:
  ...

Bare repo 使用 Git 版本 1.8.2.1,客户端使用 1.7.12.4,传输是 SSH。

也许答案实际上是this one hereThis answer 确认。如果选择的符号引用都指向与 HEAD 相同的修订版,客户端将猜测要使用哪个分支。

【问题讨论】:

  • 你能设置一个复制器吗?涉及哪些版本的 git(在 clone-ee 和 clone-er 上)?使用什么交通工具?
  • 是的,这也发生在我身上。似乎客户端正在选择一个分支,该分支指向远程的HEAD 指向的同一提交。这发生在我删除 master 分支并将另一个新分支设置为默认分支之后。目前还有一些其他分支也指向这个新默认分支的最新提交。

标签: git git-clone


【解决方案1】:

Git 1.8.5 开头,服务器将在“symref”功能中发送HEAD 指向的实际分支名称。如果您的客户端和服务器都比 Git 1.8.5 更新,它将更新 HEAD正确

在此之前,客户端将通过比较 HEAD(最终)指向的对象 ID 与所有分支的所有对象 ID 来猜测 HEAD 可能指向的内容。它更喜欢名为refs/heads/master 的分支:如果HEADmaster 都指向相同的对象ID,则克隆会将新存储库中的默认分支设置为master

否则,具有匹配 OID 的第一个分支(当分支按字母数字排序时)将是默认分支。如果没有分支具有匹配的 OID,则 HEAD 将直接设置为对象 ID(即分离的 HEAD)。

【讨论】:

  • Beginning with Git 1.8.5, the server will send the actual branch name that HEAD points to -- 我不明白。我的理解是 HEAD 是对当前签出分支中最后一次提交的引用。这句话暗示 HEAD 独立于签出分支。那么从 Git 1.8.5 开始会使用哪个分支呢?
  • HEAD 实际上不是指向提交的指针;它是一个指向分支的指针。这就是确定“当前签出分支”实际上是什么的原因。因此,要确定最后一次提交,您首先查看指向(例如)masterHEAD,而 master 实际上指向一个提交。
  • (请注意,从技术上讲,我应该说,HEAD通常不是指向提交的指针。如果您进入“分离的 HEAD 状态” ,你直接签出一个提交而不是一个分支,那么HEAD实际上将指向一个提交。)
  • 这种方法对我有用——我登录到保存 Git 存储库的远程,并更新了存储库文件夹中的 HEAD 文件。我将它从“ref:refs/heads/master”更改为“ref:refs/heads/develop”。然后我在本地机器上做了一个新的 checkout,在 Git clone 之后默认选择了“develop”分支。
【解决方案2】:

这实际上是 HEAD 所指向的。使用git symbolic-ref HEAD refs/heads/mybranch 设置 HEAD。 (来源:http://feeding.cloud.geek.nz/posts/setting-default-git-branch-in-bare/

【讨论】:

  • 当我研究这个时,我偶然发现了那个网站 - 正如我在另一个答案中评论的那样,这是一个不正确的案例。肯定还有更多事情要做,因为我绝对没有得到裸仓库 HEAD 中引用的分支。
【解决方案3】:

一个裸仓库也有一个HEAD。这就是你克隆它时得到的。

来自git clone documentation

将存储库克隆到新创建的目录中,为克隆存储库中的每个分支创建远程跟踪分支(使用git branch -r 可见),并创建并签出从克隆存储库的当前活动分支派生的初始分支.

关于“当前活动分支”的部分是指远程的HEAD 修订版。

如果您想要不同的行为,可以使用--branch-b

--branch &lt;name&gt;
-b &lt;name&gt;
不要将新创建的HEAD 指向克隆存储库的HEAD 指向的分支,而是指向&lt;name&gt; 分支。在非裸存储库中,这是要签出的分支。 --branch 还可以在结果存储库中的该提交处获取标签并分离 HEAD

【讨论】:

  • 我的问题是它似乎不是真的。在远程裸仓库中,HEAD 包含“ref: refs/heads/live”。当我克隆时,我被指向另一个分支。现在,事实证明,该分支上的最后一次提交是从“远程跟踪分支'origin/live'”合并到分​​支中的。有些东西很奇怪。
  • 无法访问您的存储库,我无法进一步评论,但默认情况下您确实获得了 HEAD。
【解决方案4】:

它是origin/HEAD。但是,如果您想要“origin/master”之类的名称,则必须像这样解析文件

cat .git/refs/remotes/origin/HEAD | awk '{ print $2 }'

【讨论】:

  • git 目录并不总是.git(例如在子模块中),所以你应该使用rev-parse --git-dir 来找到它
【解决方案5】:

如果要手动检查源远程的默认分支,这应该可以可靠地工作:

git switch $(cat $(git rev-parse --git-dir)/refs/remotes/origin/HEAD | cut -d'/' -f4)

【讨论】:

    猜你喜欢
    • 2016-07-11
    • 2014-07-05
    • 2011-08-08
    • 2018-08-08
    • 1970-01-01
    • 1970-01-01
    • 2016-09-30
    • 2021-05-06
    相关资源
    最近更新 更多