我的团队在使用 dev 和 master 作为默认分支的几个回购协议中交替使用,我想编写一个脚本,在进入目录时检查默认分支。
当在这些回购协议中打开拉请求时,它们或者默认为“ dev”,或者默认为“ master”作为合并目标。
我知道如何设置这些信息,但不检索它们: Https://help.github.com/articles/setting-the-default-branch/
是否有 git 命令可用于确定远程存储库的默认分支?
下面列出了默认的 本地存储库分支:
git rev-parse --abbrev-ref origin/HEAD
GitHub API可以使用它的 CLI gh:
gh
gh api /repos/{owner}/{repo} --jq '.default_branch'
这对我来说适用于 Git 2.1.10,使用从 GitHub 克隆的存储库:
git branch -r --points-at refs/remotes/origin/HEAD
这种方法的一个主要问题是它列出了指向 HEAD 的 每个远程分支; 然而,输出包含一个提示:
origin/HEAD -> origin/master origin/master origin/test123
所以你可以用 grep或者类似的方法对输出进行后期处理,找到带箭头的那个:
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
用 git2.9.4(但可能适用于其他版本)在从 Github 克隆的回购中进行了测试:
git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'
输出样本:
master
Git 符号参考有一个 短选项,所以我的首选命令是:
$ basename $(git symbolic-ref --short refs/remotes/origin/HEAD) master
我找到了一种方法来检测默认分支(如果它不是 master 的话)。
git remote show [your_remote] | sed -n '/HEAD branch/s/.*: //p'
我用 Gitlab 的多重回购测试过,效果很好。 (在大多数情况下,[your_remote]将是 origin,运行 git remote检查您的远程名称)
[your_remote]
origin
git remote
到目前为止,似乎没有一个答案是不需要克隆的
这需要 git2.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-name别名,我只是觉得它很有用。
upstream-name
git rev-parse --abbrev-ref origin/HEAD将打印 origin/<default-branch-name>。 git symbolic-ref的答案做同样的事情,但需要一个更长的参数。
origin/<default-branch-name>
git symbolic-ref
如果 origin存储库更改其默认分支名称,那么 git remote set-head origin -a将检索新的默认分支名称。
git remote set-head origin -a
如果你想得到一个 GitHub默认分支,而不是其他的 git 服务器:
你可以使用 /repos GitHub API得到默认的分支,它是响应的 default_branch字段:
/repos
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
如果你知道它总是从回购的根目录调用,它可以简化为
[ -f .git/refs/heads/master ] && echo master || echo main
我在我的 Git 别名中使用它,比如: https://github.com/henrik/dotfiles/commit/6815bd95770afab2936fb6202b1ee5e82cb9662b
所有其他的答案都做了太多的假设,这是唯一对我有效的方法。无论您当前在哪个分支上,这都是可行的,不假定 origin/HEAD ref 在本地存在,并且即使当前的默认分支已经更改,它也将始终反映该分支。
origin/HEAD
唯一的缺点是它改变了本地的 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参数的简短变体)。
git branch
如果您的 shell 没有 rev命令,您可以改用 awk:
rev
awk
git branch -rl '*/HEAD' | awk -F/ '{print $NF}'
使用 gh cli 工具(经过测试的 v2.0.0)可以做到这一点
gh repo view --json defaultBranchRef --jq .defaultBranchRef.name
正如其他回答者所指出的那样,默认分支的概念是 GitHub 的东西,这对 Git 来说(从崇高的意义上来说)没有什么意义(这里有一个相当不错的评论(如果没有得到足够的重视) : https://stackoverflow.com/a/65710958/2521092) ,但是在实践中,我们都知道这意味着什么。
自从最初提出这个问题以来,Git 2.28添加了 init.defaultBranch,允许与 master不同的初始分支,现在很多项目都在使用 main。很好。这里的大多数答案依赖于检查一个远程,但是这实际上依赖于那里的 生存一个远程,并且存在一个可靠和一致的命名方案到这些远程。这些可能(越来越多?)合理的假设,但这并不是一个保证,我不认为这里的任何一个主要答案都能很好地失败。
init.defaultBranch
main
此外,我的主要用例是为各种 git 别名(例如 lm = log main..HEAD)使用默认分支的名称。我希望使用相同的别名,而不会想太多,不管是使用 master的外部回购,还是使用 main的本地回购,没有远程控制。Git 及其配置无法真正“存储”信息,因此无法提前设置当前存储库的主分支是什么。因此,任何想要在主分支和 HEAD 之间显示提交的别名都不能假定 git log master..HEAD或 git log main..HEAD可以工作。
lm = log main..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
lm = "!git log $(git default-branch)..HEAD"
default-branch = "!git branch --sort=-refname | grep -o -m1 '\\b\\(main\\|master\\|dev\\)\\b'"
这只是获取分支名称,然后在已定义的列表中找到第一个分支。如果有一个 main,使用它; 如果没有,并且有一个 master,使用它。我也有 dev在那里作为一个三选项,一些人使用。
dev
这有点类似于@henrik-n 在 https://stackoverflow.com/a/66622363/2521092中的功能,但是我是在 Git 本身而不是 shell 中完成的,我认为它有一些更多的可选性。
我会在其他答案的基础上再加一个答案。我不喜欢任何其他的答案,因为查询一个远程缓慢,但我也不想要一个“本地唯一”的解决方案。
我使用这个(长)别名:
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"
以上基本上是这样做的:
这适用于99% 的用例(以及我所有的用例) ,包括:
您仍然可以通过创建一个名为 main或 master(或两者兼有)的本地分支轻松地“破坏”它,即使它实际上不是默认分支。如果您没有远程控制器,并且您的默认分支名称既不是 main也不是 master,那么这也会失败。但在这些情况下,你最有可能 努力打破它。;-)
我首先检查 main,因为如果你同时拥有 main和 还有,你很可能正在从 master切换到 main的过程中。
来自 git 2.28.0及以上版本:
$ git config --get init.defaultBranch || echo master