回答你的问题存在两个问题
你提到了 main
和 master
。现在,第一个问题是实际上目前没有任何默认分支。虽然有一些类似的东西,但由于尚未达成共识,所以没有保证的方法来查询它:并非每个人都安装了 Git 版本 2.28 或更高版本。
话虽如此,运行以下命令:
git config --get init.defaultBranch
may会在你自己的Git存储库中生成一些内容,如果生成了并且你的Git版本是2.28或更高,
你的 Git将使用其作为运行
git init
时未命名分支的默认名称。(另请参见
提交8747ebb7cde9e90d20794c06e6806f75cd540142。)
请注意,如果有人运行:
git init --initial-branch=xyzzy
创建一个新的空仓库时,在这个新的空仓库中,未出现过的分支的名称将是xyzzy
,无论是否存在init.defaultBranch
设置以及其中可能包含了什么。同时,--initial-branch
选项也首次出现在Git 2.28中。
HEAD
针对您关于git - how to get default branch?的问题:
该问题可以改成:为什么git remote show origin
没有显示出master
,而是作为HEAD branch
的develop
?
git remote show
命令和git ls-remote
命令(试试看)都是通过调用其他Git仓库并从中获取信息完成工作的。在讨论这些信息之前,让我们先来看一下HEAD
在您自己的仓库中是如何工作的。
Git仓库本质上是由一系列提交组成的集合。每个提交都有一个唯一的哈希ID。所有的Git系统都使用特定算法——目前是SHA-1,但计划切换到SHA-256——根据提交的内容计算哈希ID,以便所有Git系统都针对相同的提交得到相同的哈希ID。
这就是Git在分发提交方面的工作方式。每个仓库都有自己的完整提交集合。当您交叉连接一对Git仓库(例如您自己的仓库和一个名为origin
的远程仓库)时,它们会交换哈希ID。由于哈希ID唯一地标识提交,因此发送者可以列出一个哈希ID,接收者可以立即从中判断他是否拥有该提交或需要该提交。加入一些基于提交图形结构的优化,我们就有了大多数需要的have/want协议交换部分。
然而,每个Git都使用名称来查找其自己仓库中的提交:分支名称、标签名称和其他类似的名称。这些名称与哈希ID一起使用,以查找某个特定的提交。那些提交然后也能够查找到任何早期的提交。
为了发送提交,在git fetch
匹配中的发送Git会列出他的分支、标签和其他类似的名称,以便接收Git可以确定需要请求哪些提交(如果有的话)。您可以使用git for-each-ref
列出自己的名称——全部或某个特定子集。默认情况下,将列出以refs/
开头的所有名称。
上面的图片中还缺少一个部分,那就是特殊名称
HEAD
。这个特殊名称——它不以
refs/
开头,并且Git在各种特殊方式下都会在内部使用它——通常是Git所谓的一个
符号引用(symbolic ref),我们可以使用
git symbolic-ref
命令来读取它。
$ git symbolic-ref HEAD
refs/heads/master
这告诉我们在这个Git库中,当前分支为名为master
的分支。(分支名称都以refs/heads/
开头;其他名称以其他基于refs/
的前缀开头。)在一个非裸的Git存储库中(通常我们使用的那种),这意味着有人运行了git checkout master
或git switch master
。
当我们使用git ls-remote
连接到其他Git时,他们的 Git会为我们运行git for-each-ref
来列出他们的名称。但他们会在列表前加上HEAD
的值,如果我们添加--symref
选项,1就可以得到他们的HEAD
两个方式:
ref: refs/heads/master HEAD
72c4083ddf91b489b7b7b812df67ee8842177d98 HEAD
71ca53e8125e36efbda17293c50027d31681a41f refs/heads/maint
72c4083ddf91b489b7b7b812df67ee8842177d98 refs/heads/master
a3ce27912f980d787926b113d17f1f532e50162a refs/heads/next
[snip]
所以这告诉我,他们的Git存储库将master
设置为它们的HEAD
。第一行输出直接明确了这一点;接下来的几行显示他们的HEAD
和refs/heads/master
都指向提交72c4083ddf91b489b7b7b812df67ee8842177d98
,虽然不太明确。2
git remote show
命令具有调用其他Git的能力。3 这意味着他们可以让其列出其作为HEAD
的分支。 当您看到:
HEAD branch: develop
这只是意味着他们的Git将他们的
HEAD
附加到他们的分支名
develop
。如果他们的存储库不是bare,则这意味着他们运行了
git checkout develop
或
git switch develop
。
如果他们有一个bare存储库,他们仍然可以使用
git --work-tree=... checkout
或
GIT_WORK_TREE=... git checkout
或直接运行
git symbolic-ref
来获得相同的效果。他们的
HEAD
所附加的分支名称不一定是他们的
master
或
main
,如果他们有一个的话,他们控制哪个分支名称(如果有的话)存储在他们的
HEAD
中。
这没有太大的意义。如果他们的
HEAD
命名为他们的
develop
,那只是意味着他们的
HEAD
附加到他们的
develop
。既然他们的分支名称是他们自己的而不是你的,那对你来说并不重要。
但是有一个地方确实很重要。如果你运行:
git clone <url>
而不是,比如说:
git clone -b somebranch <url>
如果你想要让你的 Git 调用他们的 Git 并“询问他们建议使用哪个分支名称”,那么你需要使用 -b branch
,这表示你选择这个分支;如果你不提供此参数,则表示你让你的 Git 采用他们的建议。建议使用的分支名称是他们的 HEAD
所指向的分支。因此,无论是谁——控制另一个 Git 存储库的人——都应该采用任何可用手段将他们的 HEAD
连接到他们个人建议的分支名称。
你无需遵循他们的建议。你在克隆时已经有了自己的分支名称。你不需要使用与他们相同的名称。这取决于你自己。大多数人主要使用相同的名称来使事情更容易理解。
1旧版本的 Git 不支持此 --symref
选项。当新版 Git 与无法进行符号引用传输的旧版 Git 通信时,新版 Git 必须对旧版 Git 的 HEAD
进行猜测。这是一种有点丑陋的情况,我们假设您在这里使用的是全新的 Git 版本。
2这向您展示了旧版 Git 如何进行猜测:如果 HEAD
的哈希 ID 与一个分支名称完全匹配,则表示这是该分支名称。但是,如果 HEAD
的哈希 ID 与两个、三个或更多分支名称的哈希 ID 匹配怎么办?那就会变得很复杂。
3在现代 Git 中,这是您使用 git remote show
的默认方式。我不确定是否曾经存在非默认方式。然而,git remote
命令有许多子命令,其中许多子命令不需要调用其他 Git。
/usr/bin/git
,另一个是/usr/local/bin/git
,前者/usr/bin/git init
创建带有“master”的存储库,而后者/usr/local/bin/git init
创建带有“main”的存储库 - 那么哪个是“默认”的?在我看来,并没有这样的事情,每个存储库都有自己的默认值,不一定是“master”或“main”;它可以是任何东西,例如“default”或“trunk”。 - phdgit remote show origin
,然后查找带有HEAD branch: main
文本的部分(main在克隆时将被替换为默认分支)。这在您链接的页面上有提到,并且应该可以解决问题。如果还是不行,那么您或许应该提出相关问题。我之所以这么说是因为如果您没有说明为什么不适用于您或者您的情境有何不同,那么这个问题很可能会被关闭并作为重复问题,因为您最终可能会得到完全相同的答案。除非您告诉我们在您的情况下有哪些不同之处。 - Lasse V. Karlsenorigin
:-) - phdHEAD
并映射回本地分支。但是,如果有多个分支和多个远程分支,那么就糟糕了。所有远程分支和本地分支都是相等的,而默认的概念在用户的头脑中(双关语),没有办法通过编程方式提取知识。我唯一看到的方法是在您的别名/脚本中设置一些合理的默认值(origin
和master
),但允许用户使用配置或参数进行覆盖。 - phdorigin
没有问题(现在不会更改),而且我还没有使用多个远程 - 尽管在我的实际情况中,当查看git remote show origin
的输出时,我确实看到develop
作为HEAD branch
,而它应该输出master
(顺便说一下,master
也被列为远程分支之一..)。为什么会这样?我完全不理解... - user3341592