【问题标题】:git - how to get default branch?git - 如何获取默认分支?
【发布时间】:2015-02-23 03:08:59
【问题描述】:

我的团队交替使用 dev 和 master 作为几个 repos 的默认分支,我想编写一个脚本,在进入目录时检查默认分支。

当在其中一些存储库中打开拉取请求时,它们默认将“dev”或“master”作为合并目标。

我了解如何设置此信息但不检索它: https://help.github.com/articles/setting-the-default-branch/

是否有 git 命令可用于确定远程存储库的默认分支?

【问题讨论】:

  • 默认分支是github的东西,不是git的东西。
  • 你可以使用 GitHub API,如这个问题:stackoverflow.com/questions/16500461/…
  • @IsmailBadawi 真的吗?在创建本地裸仓库并对其执行克隆时,仍然必须有一些逻辑来确定默认签出哪个分支,对吧?
  • 以下解决方案都不能可靠地为我工作:如果我在分支feature,从develop 分叉,它将返回我develop 而不是master(或@ 987654328@,其中develop 是一个分支)...有什么帮助吗?

标签: git github branch


【解决方案1】:

我找到了一种方法来检测默认分支(如果它不是主分支)。

git remote show [your_remote] | sed -n '/HEAD branch/s/.*: //p'

我用来自 gitlab 的多个 repo 对其进行了测试,它运行良好。 (大多数情况下[your_remote] 将是origin,运行git remote 以检查您的遥控器的名称)

【讨论】:

  • 这对我来说效果很好,除了 cut 命令在实际分支名称之前留下一个空格,这在脚本中使用它时可能会导致问题。我最终使用了git remote show upstream | grep "HEAD branch" | sed 's/.*: //'
  • 目前为止最好的方法。由于某些原因,我什至没有 refs/remotes/origin/HEAD。
  • 我把它更新成这样去掉空格git remote show origin | grep 'HEAD branch' | cut -d' ' -f5
  • 请注意,这可能不适用于某些(旧)版本的 git,前提是您的 HEAD 不明确。参见例如this post
  • 如果 git 在非英语语言环境下运行,这将不起作用。例如,对于德语语言环境,HEAD branch 拼写为 Hauptbranch。要解决此问题:LC_ALL=C git remote show origin | sed -n '/HEAD branch/s/.*: //p'
【解决方案2】:

在从 Github 克隆的 repo 中使用 git 2.9.4(但可能适用于其他版本)进行测试:

$ git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'
master

【讨论】:

  • 如果我更改服务器端 (github) 上的默认分支,这仍然会在旧的但当前的克隆中获得旧的默认值(但新的克隆很好)。如何在这里强制更新?
  • 也许我做错了什么,但是当我运行它时,我得到:fatal: ref refs/remotes/origin/HEAD is not a symbolic ref with Git 2.19.1。
  • 此方法可能会失败或返回不正确的结果。 ref 可能是无法解析为分支的哈希,而不是符号引用。这也可以通过查看 HEAD 来解决。尽管如此,在 6528 个存储库中,我在 172 个案例中检查了两个 git symbolic-ref 方法返回错误结果(例如 master 而不是 develop 用于 Alfresco/chef-alfresco)。 @Radon8472 提出的 git remote show 方法更可靠,在我手工验证的 172 个发散案例中,有几个似乎返回了正确的结果。
  • 你也可以使用 basename 代替 sed basename $(git symbolic-ref refs/remotes/origin/HEAD)
  • 从上游同步这个符号引用,git remote set-head origin --auto。这会更新git remote show 中看到的内容和此处引用的符号引用。
【解决方案3】:

@987654321@ origin/HEAD 将打印origin/<default-branch-name>git symbolic-ref 的答案在做同样的事情,但需要更长的参数。

如果origin 存储库更改其默认分支名称,则@987654323@ origin -a 将检索新的默认分支名称。

【讨论】:

  • 这比git remote show 运行得快很多,因为它使用本地信息而不轮询远程。您可以剪掉前 7 个字符(即“origin/”)并仅使用 git rev-parse --abbrev-ref origin/HEAD | cut -c8- 获取分支名称。
  • 这实际上不是规范答案吗,因为它使用管道命令并且不需要 git 本身之外的任何实用程序?
  • 回答自己 - 这不是规范的答案,因为它只适用于通过从远程克隆创建的存储库 - 而不是来自您创建的存储库,然后通过 git remote add 添加远程并推送到它。
  • (仍然赞成,因为它是脚本的可能用例中的最佳答案,您知道您已经从远程克隆了 repo)
  • 对我不起作用:按答案执行时,我得到的唯一标准输出是origin/HEAD,还有错误warning: ignoring dangling symref refs/remotes/origin/HEADfatal: ambiguous argument 'origin/HEAD': unknown revision or path not in the working tree.。如果我将-- . 附加到命令后,它会显示warning: ignoring dangling symref refs/remotes/origin/HEADfatal: bad revision 'origin/HEAD'。但是,git symbolic-ref 回答这个答案是指对我有用。
【解决方案4】:

这个问题有点老了,但如果最近有人遇到这个问题......

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% 的时间都使用“上游”和“起源”作为我的遥控器(当我使用 Fork & Pull 工作流程时使用“上游”......这很常见)。您的用例可能不需要 upstream-name 别名,我只是觉得它很有用。

【讨论】:

  • 一个可能的 PowerShell 解决方案:(git remote show origin | Select-String "HEAD branch: " -Raw).Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[2]
  • git remote show 很慢,因为它查询服务器。使用 -n 选项会更快,但只会返回已知的分支列表。这可能不是最好的解决方案,但可以编写以下内容:git remote show origin -n | grep -c main &amp;&gt; /dev/null &amp;&amp; echo main || echo master
  • 对我不起作用,它显示“连接超时”。我猜这是因为命令访问网络而不是使用本地可用的信息,我认为值得在帖子中提及。
【解决方案5】:

目前看来没有不需要克隆的答案

这需要 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

【讨论】:

  • 感谢您的精彩回答。我添加了 awk 以获取分支名称:git ls-remote --symref https://github.com/hnakamur/ltsvlog HEAD | awk '/^ref:/ {sub(/refs\/heads\//, "", $2); print $2}'
【解决方案6】:

git symbolic-ref 有一个 --short 选项。所以我的首选命令:

$ basename $(git symbolic-ref --short refs/remotes/origin/HEAD) 
master

【讨论】:

  • 对于远程,它仍然是git symbolic-ref --short refs/remotes/origin/HEAD | sed 's@^origin/@@'
  • 这是一个路径,所以在大多数 POSIX-y shell 中,您也可以只使用 basename 来获取最后一个组件。 :D basename $(git symbolic-ref --short refs/remotes/origin/HEAD)
  • basename 不适用于所有分支名称,因为它们可以包含斜杠
【解决方案7】:

以下命令将列出 HEAD 分支,无论您如何命名遥控器:

git branch --remotes --list '*/HEAD'

从中您可以像这样提取默认分支:

git branch -rl '*/HEAD' | rev | cut -d/ -f1 | rev

(使用 git branch 参数的短变体)。

【讨论】:

  • 我在某个地方工作,stage 用作开发的主干,master 用于部署。这给了我stage,这就是我想要的——谢谢!
【解决方案8】:

我只是想要一个 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

【讨论】:

    【解决方案9】:

    如果你喜欢这个问题,你想获得一个 GitHub 默认分支——而不是其他一些 git 服务器:

    您可以使用/repos GitHub API 获取默认分支。这是响应的default_branch 字段:

    $ curl -s https://api.github.com/repos/darthwalsh/bootstrappingCIL | \
          jq --raw-output .default_branch
    master
    

    【讨论】:

      【解决方案10】:

      这适用于 Git 2.1.10,使用从 GitHub 克隆的存储库:

      git branch -r --points-at refs/remotes/origin/HEAD
      

      这种方法的一个主要问题是它列出了 每个 指向 HEAD 的远程分支;但是,输出包含一个提示:

        origin/HEAD -> origin/master
        origin/master
        origin/test123
      

      因此您可以使用grep 或类似名称对输出进行后处理,以找到带有箭头的输出:

      git branch -r --points-at refs/remotes/origin/HEAD | grep '\->' | cut -d' ' -f5 | cut -d/ -f2
      

      【讨论】:

      • 值得指出的是,.git/refs/remotes/origin/HEAD 只有在你克隆了 repo 的情况下才会存在,而不是在你创建/创作它的情况下。 git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/master 可用于链接参考文献(但这违背了这个问题的重点:))
      【解决方案11】:

      这可以通过 gh cli 工具获得(已测试 v2.0.0)

      gh repo view --json defaultBranchRef --jq .defaultBranchRef.name

      【讨论】:

        【解决方案12】:

        正如其他回答者所指出的,默认分支的概念是 GitHub 的东西,对于 Git 并没有真正意义(在崇高的意义上)(这里有一个相当好的(如果不被欣赏的)评论进入它bit:https://stackoverflow.com/a/65710958/2521092) 但在实践中,我们都知道这意味着什么。

        自从最初提出这个问题以来,Git 2.28 添加了init.defaultBranch,允许与master 不同的初始分支,现在很多项目都在使用main。那挺好的。这里的大多数答案都依赖于检查遥控器,但这依赖于实际上作为遥控器,并且这些遥控器存在可靠且一致的命名方案。这些可能(越来越多?)合理的假设,但这不是保证,而且我发现这里的任何主要答案都没有很好地失败。

        此外,我的主要用例是将默认分支的名称用于各种 git 别名(例如 lm = log main..HEAD)。我想使用相同的别名而不考虑太多,无论是使用master 的外部仓库还是使用main 没有远程的本地仓库。 Git 及其配置不能真正“存储”信息,因此无法提前设置当前存储库的主分支是什么。因此,任何想要显示主分支和 HEAD 之间提交的别名都不能假设 git log master..HEADgit 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 在https://stackoverflow.com/a/66622363/2521092 中所做的事情,但我是在 Git 本身而不是 shell 中做的,我认为它有更多的可选性。

        【讨论】:

        • 非常好的选择。赞成。
        【解决方案13】:

        所有其他答案都做了太多假设,这是对我有用的唯一方法。无论您当前在哪个分支上,这都有效,不假定 origin/HEAD 引用在本地存在,并且始终反映当前的默认分支,即使它已被更改。

        唯一的缺点是它改变了本地的origin/HEAD ref,但这通常不是问题。

        允许 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
        

        【讨论】:

          【解决方案14】:

          似乎是一种解决方法,但这似乎可行:

          $ cat .git/refs/remotes/origin/HEAD 
          ref: refs/remotes/origin/master
          

          【讨论】:

            【解决方案15】:

            是否有 git 命令可用于确定远程存储库的默认分支?

            不,似乎没有:

            git ls-remote -h https://github.com/<user>/<repo>
            

            这将列出所有分支,但不列出 HEAD(这是指定默认分支的 symref)

            同样,GitHub Reference API 可以列出头部,但也不包括 HEAD。

            【讨论】:

              猜你喜欢
              • 2016-07-11
              • 2012-12-06
              • 1970-01-01
              • 2021-10-20
              • 1970-01-01
              • 2011-04-05
              • 2017-08-03
              • 2014-05-22
              • 1970-01-01
              相关资源
              最近更新 更多