git - 如何获得默认分支?
git - how to get default branch?
我的团队交替使用 dev 和 master 作为多个存储库的默认分支,我想编写一个脚本来在进入目录时检查默认分支。
当在其中一些存储库中打开拉取请求时,它们默认为 'dev' 或 'master' 作为合并目标。
我了解如何设置此信息但无法检索它:
https://help.github.com/articles/setting-the-default-branch/
是否有 git 命令可用于确定远程存储库的默认分支?
Is there a git command available to determine default branch for remote repository?
没有,好像没有:
git ls-remote -h https://github.com/<user>/<repo>
这会列出所有分支,但不会列出 HEAD(这是指定默认分支的 symref)
同样,GitHub Reference API 可以列出头部,但不会包括 HEAD。
这适用于 Git 2.1.10,使用从 GitHub:
克隆的存储库
git branch -r --points-at refs/remotes/origin/HEAD
这种方法的一个主要问题是它列出了每个 指向HEAD 的远程分支;然而,输出包含一个提示:
origin/HEAD -> origin/master
origin/master
origin/test123
因此您可以 post-使用 grep
或类似方法处理输出以找到带有箭头的输出:
git branch -r --points-at refs/remotes/origin/HEAD | grep '\->' | cut -d' ' -f5 | cut -d/ -f2
似乎有点变通解决方案,但这似乎有效:
$ cat .git/refs/remotes/origin/HEAD
ref: refs/remotes/origin/master
在从 Github:
克隆的回购中使用 git 2.9.4(但可能适用于其他版本)进行测试
$ git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'
master
--short 选项 git symbolic-ref。所以我的首选命令:
$ basename $(git symbolic-ref --short refs/remotes/origin/HEAD)
master
我找到了一种检测默认分支的方法,如果它不是 master。
git remote show [your_remote] | sed -n '/HEAD branch/s/.*: //p'
我用 gitlab 的多个 repo 测试了它,它运行良好。
(在大多数情况下 [your_remote]
将是 origin
、运行 git remote
来检查您的遥控器的名称)
目前似乎没有不需要克隆的答案
这需要 git 2.8.0 或更高版本
$ git ls-remote --symref git@github.com:pre-commit/pre-commit.github.io HEAD
ref: refs/heads/real_master HEAD
e100a6a3c72b4e54f0d176f791dfd2dbd7eb5fa7 HEAD
这个问题有点老了,但万一有人最近遇到这个问题...
git remote show <remote_name> | awk '/HEAD branch/ {print $NF}'
那也只会显示分支名称,不包括任何空格或其他废话。
我喜欢使用几个 git 别名来保存它(我有很多像这样的有用别名):
upstream-name = !git remote | egrep -o '(upstream|origin)' | tail -1
head-branch = !git remote show $(git upstream-name) | awk '/HEAD branch/ {print $NF}'
我几乎 100% 的时间都使用 "upstream" 和 "origin" 作为我的遥控器("upstream" 当我使用 Fork & Pull 工作流程时......这通常是).您的用例可能不需要 upstream-name
别名,我只是觉得它很有用。
<a href="https://git-scm.com/docs/git-rev-parse#Documentation/git-rev-parse.txt---abbrev-refstrictloose" rel="noreferrer">git rev-parse --abbrev-ref</a> origin/HEAD
will print origin/<default-branch-name>
. The git symbolic-ref
答案是做同样的事情,但需要更长的参数。
如果 origin
存储库更改了其默认分支名称,则 <a href="https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emset-headem" rel="noreferrer">git remote set-head</a> origin -a
将检索新的默认分支名称。
如果喜欢这个问题,您正在尝试获得 GitHub 默认分支——而不是其他 git 服务器:
您可以使用 /repos
GitHub API 获取默认分支。这是响应的 default_branch
字段:
$ curl -s https://api.github.com/repos/darthwalsh/bootstrappingCIL | \
jq --raw-output .default_branch
master
我只是想要一个 shell 脚本来知道分支是“master”还是“main”。
为此目的,这似乎足够了:
[ -f "$(git rev-parse --show-toplevel)/.git/refs/heads/master" ] && echo master || echo main
如果知道总是从repo的根目录调用,可以简化为
[ -f .git/refs/heads/master ] && echo master || echo main
我在我的 Git 别名中使用它,如下所示:https://github.com/henrik/dotfiles/commit/6815bd95770afab2936fb6202b1ee5e82cb9662b
所有其他答案都做了太多假设,这是对我有用的唯一方法。无论您当前在哪个分支,这都有效,不假设 origin/HEAD
ref 存在于本地,并且即使它已被更改也将始终反映当前的默认分支。
唯一的缺点是它会改变本地 origin/HEAD
引用,但这通常不会成为问题。
允许 git 设置您的 origin/HEAD
,确定自动使用哪个分支:
$ git remote set-head origin --auto
origin/HEAD set to main
然后,获取包含默认分支名称的字符串:
$ git rev-parse --abbrev-ref origin/HEAD
origin/main
或者,对于单行解决方案:
$ git remote set-head origin --auto >/dev/null 2>&1 && git rev-parse --abbrev-ref origin/HEAD
origin/main
无论您如何命名遥控器,以下命令都会列出 HEAD 分支:
git branch --remotes --list '*/HEAD'
您可以从中提取默认分支,如下所示:
git branch -rl '*/HEAD' | rev | cut -d/ -f1 | rev
(使用 git branch
参数的简短变体)。
这可以通过 gh cli 工具获得(已测试 v2.0.0)
gh repo view --json defaultBranchRef --jq .defaultBranchRef.name
正如其他回答者所指出的,默认分支的概念是 GitHub 的东西并没有真正意义(在崇高的意义上)Git(有一个相当好的(如果被低估了)这里的评论有点深入:)但在实践中,我们都知道这意味着什么。
自从最初提出这个问题后,Git 2.28 添加了 init.defaultBranch
,允许与 master
不同的初始分支,现在很多项目都在使用 main
.那挺好的。这里的大部分答案都依赖于检查遥控器,但这依赖于实际上 是 遥控器,并且这些遥控器存在可靠且一致的命名方案。这些可能是(越来越多?)合理的假设,但这并不能保证,而且我发现这里的任何主要答案都不会很好地失败。
此外,我的主要用例是使用默认分支的名称作为各种 git 别名(例如 lm = log main..HEAD
)。我想使用相同的别名而不考虑太多,无论外部回购使用 master
还是本地使用 main
没有远程。 Git 及其配置无法真正“存储”信息,因此无法提前设置当前存储库的主分支是什么。因此,任何想要显示主分支和 HEAD 之间的提交的别名都不能假设 git log master..HEAD
或 git log main..HEAD
会起作用。
因此,我在 Git 中定义了一个 default-branch
别名,用于确定默认分支,然后将其提供给其他别名。这是一个痛苦,因为一个简单的 lm = log main..HEAD
必须变成 lm = "!git log $(git default-branch)..HEAD"
但我们现在是:
default-branch = "!git branch --sort=-refname | grep -o -m1 '\b\(main\|master\|dev\)\b'"
这只是获取分支名称,然后在定义的列表中找到第一个。如果有 main
,请使用它;如果没有并且有 master
,请使用它。我也有 dev
作为一些人使用的第三选项。
这有点类似于@henrik-n 在 中所做的,但我是在 Git 本身而不是 shell 中做的,我认为它有一些更多可选性。
我将根据其他答案添加另一个答案。我不喜欢任何其他答案,因为查询遥控器很慢,但我也不想要“local-only”解决方案。
我使用这个(长)别名:
head-branch = "!f() { gitHeadsDir=\"$(git rev-parse --show-toplevel)/.git/refs/heads\"; if [ -f \"$gitHeadsDir/main\" ]; then echo 'main'; elif [ -f \"$gitHeadsDir/master\" ]; then echo 'master'; else git remote show origin | grep 'HEAD branch' | cut -d' ' -f5; fi; }; f"
以上基本上是这样做的:
- 如果存在名为
main
的本地分支,则使用该分支
- 如果存在名为
master
的本地分支,则使用该分支
- 否则,返回检查遥控器(慢得多)
这适用于 99% 的用例(以及我的所有用例),包括:
- “常规”克隆存储库
- 一个全新的存储库,可能甚至没有远程(还)。
您仍然可以通过创建名为 main
或 master
(或两者)的本地分支轻松地“打破”它,即使这实际上不是默认分支。如果您没有遥控器,这也会失败,并且您的默认分支名称既不是 main
也不是 master
。但在这些情况下,您很可能试图 破坏它。 ;-)
我首先检查 main
,因为如果您同时拥有 main
和 master
,您很可能在从 master
切换到 main
的过程。
我的团队交替使用 dev 和 master 作为多个存储库的默认分支,我想编写一个脚本来在进入目录时检查默认分支。
当在其中一些存储库中打开拉取请求时,它们默认为 'dev' 或 'master' 作为合并目标。
我了解如何设置此信息但无法检索它: https://help.github.com/articles/setting-the-default-branch/
是否有 git 命令可用于确定远程存储库的默认分支?
Is there a git command available to determine default branch for remote repository?
没有,好像没有:
git ls-remote -h https://github.com/<user>/<repo>
这会列出所有分支,但不会列出 HEAD(这是指定默认分支的 symref)
同样,GitHub Reference API 可以列出头部,但不会包括 HEAD。
这适用于 Git 2.1.10,使用从 GitHub:
克隆的存储库git branch -r --points-at refs/remotes/origin/HEAD
这种方法的一个主要问题是它列出了每个 指向HEAD 的远程分支;然而,输出包含一个提示:
origin/HEAD -> origin/master
origin/master
origin/test123
因此您可以 post-使用 grep
或类似方法处理输出以找到带有箭头的输出:
git branch -r --points-at refs/remotes/origin/HEAD | grep '\->' | cut -d' ' -f5 | cut -d/ -f2
似乎有点变通解决方案,但这似乎有效:
$ cat .git/refs/remotes/origin/HEAD
ref: refs/remotes/origin/master
在从 Github:
克隆的回购中使用 git 2.9.4(但可能适用于其他版本)进行测试$ git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'
master
--short 选项 git symbolic-ref。所以我的首选命令:
$ basename $(git symbolic-ref --short refs/remotes/origin/HEAD)
master
我找到了一种检测默认分支的方法,如果它不是 master。
git remote show [your_remote] | sed -n '/HEAD branch/s/.*: //p'
我用 gitlab 的多个 repo 测试了它,它运行良好。
(在大多数情况下 [your_remote]
将是 origin
、运行 git remote
来检查您的遥控器的名称)
目前似乎没有不需要克隆的答案
这需要 git 2.8.0 或更高版本
$ git ls-remote --symref git@github.com:pre-commit/pre-commit.github.io HEAD
ref: refs/heads/real_master HEAD
e100a6a3c72b4e54f0d176f791dfd2dbd7eb5fa7 HEAD
这个问题有点老了,但万一有人最近遇到这个问题...
git remote show <remote_name> | awk '/HEAD branch/ {print $NF}'
那也只会显示分支名称,不包括任何空格或其他废话。
我喜欢使用几个 git 别名来保存它(我有很多像这样的有用别名):
upstream-name = !git remote | egrep -o '(upstream|origin)' | tail -1
head-branch = !git remote show $(git upstream-name) | awk '/HEAD branch/ {print $NF}'
我几乎 100% 的时间都使用 "upstream" 和 "origin" 作为我的遥控器("upstream" 当我使用 Fork & Pull 工作流程时......这通常是).您的用例可能不需要 upstream-name
别名,我只是觉得它很有用。
<a href="https://git-scm.com/docs/git-rev-parse#Documentation/git-rev-parse.txt---abbrev-refstrictloose" rel="noreferrer">git rev-parse --abbrev-ref</a> origin/HEAD
will print origin/<default-branch-name>
. The git symbolic-ref
答案是做同样的事情,但需要更长的参数。
如果 origin
存储库更改了其默认分支名称,则 <a href="https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emset-headem" rel="noreferrer">git remote set-head</a> origin -a
将检索新的默认分支名称。
如果喜欢这个问题,您正在尝试获得 GitHub 默认分支——而不是其他 git 服务器:
您可以使用 /repos
GitHub API 获取默认分支。这是响应的 default_branch
字段:
$ curl -s https://api.github.com/repos/darthwalsh/bootstrappingCIL | \
jq --raw-output .default_branch
master
我只是想要一个 shell 脚本来知道分支是“master”还是“main”。
为此目的,这似乎足够了:
[ -f "$(git rev-parse --show-toplevel)/.git/refs/heads/master" ] && echo master || echo main
如果知道总是从repo的根目录调用,可以简化为
[ -f .git/refs/heads/master ] && echo master || echo main
我在我的 Git 别名中使用它,如下所示:https://github.com/henrik/dotfiles/commit/6815bd95770afab2936fb6202b1ee5e82cb9662b
所有其他答案都做了太多假设,这是对我有用的唯一方法。无论您当前在哪个分支,这都有效,不假设 origin/HEAD
ref 存在于本地,并且即使它已被更改也将始终反映当前的默认分支。
唯一的缺点是它会改变本地 origin/HEAD
引用,但这通常不会成为问题。
允许 git 设置您的 origin/HEAD
,确定自动使用哪个分支:
$ git remote set-head origin --auto
origin/HEAD set to main
然后,获取包含默认分支名称的字符串:
$ git rev-parse --abbrev-ref origin/HEAD
origin/main
或者,对于单行解决方案:
$ git remote set-head origin --auto >/dev/null 2>&1 && git rev-parse --abbrev-ref origin/HEAD
origin/main
无论您如何命名遥控器,以下命令都会列出 HEAD 分支:
git branch --remotes --list '*/HEAD'
您可以从中提取默认分支,如下所示:
git branch -rl '*/HEAD' | rev | cut -d/ -f1 | rev
(使用 git branch
参数的简短变体)。
这可以通过 gh cli 工具获得(已测试 v2.0.0)
gh repo view --json defaultBranchRef --jq .defaultBranchRef.name
正如其他回答者所指出的,默认分支的概念是 GitHub 的东西并没有真正意义(在崇高的意义上)Git(有一个相当好的(如果被低估了)这里的评论有点深入:)但在实践中,我们都知道这意味着什么。
自从最初提出这个问题后,Git 2.28 添加了 init.defaultBranch
,允许与 master
不同的初始分支,现在很多项目都在使用 main
.那挺好的。这里的大部分答案都依赖于检查遥控器,但这依赖于实际上 是 遥控器,并且这些遥控器存在可靠且一致的命名方案。这些可能是(越来越多?)合理的假设,但这并不能保证,而且我发现这里的任何主要答案都不会很好地失败。
此外,我的主要用例是使用默认分支的名称作为各种 git 别名(例如 lm = log main..HEAD
)。我想使用相同的别名而不考虑太多,无论外部回购使用 master
还是本地使用 main
没有远程。 Git 及其配置无法真正“存储”信息,因此无法提前设置当前存储库的主分支是什么。因此,任何想要显示主分支和 HEAD 之间的提交的别名都不能假设 git log master..HEAD
或 git log main..HEAD
会起作用。
因此,我在 Git 中定义了一个 default-branch
别名,用于确定默认分支,然后将其提供给其他别名。这是一个痛苦,因为一个简单的 lm = log main..HEAD
必须变成 lm = "!git log $(git default-branch)..HEAD"
但我们现在是:
default-branch = "!git branch --sort=-refname | grep -o -m1 '\b\(main\|master\|dev\)\b'"
这只是获取分支名称,然后在定义的列表中找到第一个。如果有 main
,请使用它;如果没有并且有 master
,请使用它。我也有 dev
作为一些人使用的第三选项。
这有点类似于@henrik-n 在
我将根据其他答案添加另一个答案。我不喜欢任何其他答案,因为查询遥控器很慢,但我也不想要“local-only”解决方案。
我使用这个(长)别名:
head-branch = "!f() { gitHeadsDir=\"$(git rev-parse --show-toplevel)/.git/refs/heads\"; if [ -f \"$gitHeadsDir/main\" ]; then echo 'main'; elif [ -f \"$gitHeadsDir/master\" ]; then echo 'master'; else git remote show origin | grep 'HEAD branch' | cut -d' ' -f5; fi; }; f"
以上基本上是这样做的:
- 如果存在名为
main
的本地分支,则使用该分支 - 如果存在名为
master
的本地分支,则使用该分支 - 否则,返回检查遥控器(慢得多)
这适用于 99% 的用例(以及我的所有用例),包括:
- “常规”克隆存储库
- 一个全新的存储库,可能甚至没有远程(还)。
您仍然可以通过创建名为 main
或 master
(或两者)的本地分支轻松地“打破”它,即使这实际上不是默认分支。如果您没有遥控器,这也会失败,并且您的默认分支名称既不是 main
也不是 master
。但在这些情况下,您很可能试图 破坏它。 ;-)
我首先检查 main
,因为如果您同时拥有 main
和 master
,您很可能在从 master
切换到 main
的过程。