【问题标题】:How to check if remote branch exists on a given remote repository?如何检查给定远程存储库上是否存在远程分支?
【发布时间】:2012-01-03 15:58:48
【问题描述】:

如果特定分支存在于给定的远程存储库中,我需要对特定分支进行子树合并。问题是远程仓库没有在本地签出,所以不能使用git branch -r。我只有一个远程地址,比如https://github.com/project-name/project-name.git。有没有办法仅通过远程地址列出远程分支?我找不到任何有用的东西:(

【问题讨论】:

    标签: git


    【解决方案1】:

    这对我来说是最简单的方法。 (※鱼壳)

    if test (git ls-remote | grep your-branch-name)
      echo exist
    else
      echo not_exist
    end
    

    【讨论】:

      【解决方案2】:

      怎么样

      if [ -e .git/refs/remotes/origin/mybranch ]; then
        echo remote branch still exists - locally at least
      else
        echo remote branch is gone
      fi
      

      git ls-remote 将与远程服务器交互,这 可能是也可能不是你想要的。

      【讨论】:

      • 这不适用于新鲜克隆。
      【解决方案3】:
      $ git ls-remote --heads git@github.com:user/repo.git branch-name
      

      如果找到branch-name,您将获得以下输出:

      b523c9000c4df1afbd8371324083fef218669108        refs/heads/branch-name
      

      否则将不发送任何输出。

      因此,通过管道将其发送到 wc 会得到 10

      $ git ls-remote --heads git@github.com:user/repo.git branch-name | wc -l
      

      或者,您可以在git ls-remote 上设置--exit-code 标志,如果找不到匹配的引用,它将返回退出代码2。可以直接在 shell 测试中检查结果,也可以通过检查状态变量$?

      $ git ls-remote --exit-code --heads git@github.com:user/repo.git branch-name
      

      【讨论】:

      • 我使用了git ls-remote --heads ${REPO} ${BRANCH} | grep ${BRANCH} >/dev/null,然后是if [ "$?" == "1" ] ; then echo "Branch doesn't exist"; exit; fi
      • 我花了几个小时寻找这个简洁而准确的答案,太棒了。
      • 您需要指定分支名称为/refs/heads/branch-name。否则,即使没有branch-name,也会返回分支foo/branch-name
      • 注意:如果您不想指定 repo URL,您可以指定 repo 远程名称,例如:git ls-remote --heads origin branch-name
      • 订单很重要:--exit-code 必须在 --heads 之前。
      【解决方案4】:

      这里的所有答案都是特定于 Linux shell 的,如果您处于不支持此类操作的环境(例如 Windows 的命令提示符)中,这将无济于事。

      幸运的是,git ls-remote 接受 --exit-code 参数,该参数分别根据分支是否存在返回 0 或 2。所以:

      git ls-remote --exit-code --heads origin <branch-that-exists-in-origin>

      将返回 0,并且

      git ls-remote --exit-code --heads origin <branch-that-only-exists-locally>

      将返回 2。

      对于 PowerShell,您可以简单地使用内置的真实性处理语义:

      if (git ls-remote --heads origin <branch-that-exists-in-origin>) { $true } else { $false }

      产生$true,而:

      if (git ls-remote --heads origin <branch-that-only-exists-locally>) { $true } else { $false }

      产生$false

      【讨论】:

        【解决方案5】:

        将返回名称中包含查询的所有分支(远程或本地)。

        git branch --all | grep &lt;query&gt;

        【讨论】:

          【解决方案6】:

          我将上面的一些答案合并到一个脚本中:

          BRANCHES=(develop master 7.0 7.0-master)
          ORIGIN=bitbucket
          REMOTE=github
          
          for BRANCH in "${BRANCHES[@]}"; do
            BRANCH=$(git ls-remote --heads "${ORIGIN}" "${BRANCH}" \
                | cut --delimiter=$'\t' --fields=2 \
                | sed 's,refs/heads/,,' \
                | grep --line-regexp "${BRANCH}")
            if [ -n "${BRANCH}" ]
            then
              git branch --force "${BRANCH}" "${ORIGIN}"/"${BRANCH}"
              git checkout "${BRANCH}"
              git push "${REMOTE}" "${BRANCH}"
            fi
          done
          
          git push github --tags
          

          此脚本将从远程bitbucket 中获取4 个分支,并将它们推送到远程github,然后将所有标签推送到github。 我在 Jenkins 作业中使用它,这就是为什么您看不到任何 git fetchgit pull,这已在 Jenkins 作业存储库配置中完成。

          我通常更喜欢脚本中的长格式选项。我可以使用git checkout -B 组合git branchgit checkout

          【讨论】:

            【解决方案7】:

            那么就不需要每次都手动传递仓库名称了。

            git ls-remote origin <branch>
            

            代替

            git ls-remote <full repo url> <branch>
            

            例子:

            git ls-remote git@bitbucket.org:landmarkgroupme/in-store-application.git  uat_21dec
            

            git ls-remote origin uat_21dec
            

            两者都会给出相同的输出:

            更多关于起源: Git 有“远程”的概念,它只是指向存储库其他副本的 URL。当您克隆另一个存储库时,Git 会自动创建一个名为“origin”的远程并指向它。您可以通过键入 git remote show origin 来查看有关远程的更多信息。

            【讨论】:

              【解决方案8】:

              你可以试试

              git diff --quiet @{u} @{0}
              

              这里@{u}指远程/上游,@{0}指当前本地HEAD(使用较新版本的git,@{0}可以缩写为@)。如果远程不存在,则会出错。

              用git 2.16.2(我不确定哪个版本最先有这个功能,比如git 1.7.1没有),你可以这样做

              git checkout
              

              如果存在远程分支,会有一些输出,比如

              Your branch is up to date with 'origin/master'
              

              否则没有输出。

              【讨论】:

                【解决方案9】:

                我刚试过这个:

                git ls-remote --heads 2>/dev/null|awk -F 'refs/heads/' '{print $2}'|grep -x "your-branch"|wc -l
                

                如果找到分支“your-branch”,则返回 1,否则返回 0。

                【讨论】:

                  【解决方案10】:

                  如果您的分支名称非常具体,您可能不需要使用 grep 进行简单的分支名称匹配:

                  git ls-remote --heads $(git remote | head -1) "*${BRANCH_NAME}*" | \
                      cut -d$'\t' -f2 | \
                      sed 's,refs/heads/,,' | \
                      wc -l
                  

                  适用于

                  BRANCH=master
                  BRANCH=mas
                  BRANCH=NonExistingBranch (returns 0)
                  BRANCH=ISSUE-123
                  

                  我们使用唯一的问题 ID 作为分支名称,它工作正常。

                  【讨论】:

                    【解决方案11】:
                    $ git ls-remote --heads origin <branch> | wc -l
                    

                    大部分时间都有效。

                    但如果分支部分匹配如下,则不起作用,

                    $ git branch -a
                    creative/dev
                    qa/dev
                    
                    $ git ls-remote --heads origin dev | wc -l
                    2
                    

                    使用

                    git ls-remote --heads origin <branch> | \
                        cut -d$'\t' -f2 | \
                        sed 's,refs/heads/,,' | \
                        grep ^<branch>$ | wc -l
                    

                    如果你想要一个可靠的方法。

                    如果您想在脚本中使用并且不想将origin 假定为默认远程,那么

                    git ls-remote --heads $(git remote | head -1) "$branch" | \
                        cut -d$'\t' -f2 | \
                        sed 's,refs/heads/,,' | \
                        grep ^"$branch"$ | wc -l
                    

                    应该可以。

                    请注意,git branch -a | grep ... 并不可靠,因为距离上次运行 fetch 可能有一段时间。

                    【讨论】:

                    • 对我来说,这是公认的答案,结合来自 Amitesh(短远程名称)的答案,结合来自 James Cache 的答案(grep -x "$branch"grep ^"$branch"$ 相同)。虽然在脚本中我更喜欢长格式开关:--line-regexp。另外,不需要wc -l。将空输出放在 Bash if [ -z ] 中有效地评估为 true,因此这意味着分支不存在。这样可以节省几毫秒。
                    【解决方案12】:

                    你也可以这样用:

                    git show-branch remotes/origin/<<remote-branch-name>>
                    

                    返回最新的提交和 $?是 0 否则返回 "fatal: bad sha1 reference remotes/origin/" 和 $?是 128

                    【讨论】:

                    • 这不会在检查之前从远程拉取分支,所以你不会得到最新的远程状态。
                    【解决方案13】:

                    如果它是一个 git repo 来运行,你可以在当前文件夹中使用的另一种方式

                    git branch -a | egrep 'remotes/origin/${YOUR_BRANCH_NAME}$'
                    

                    【讨论】:

                    • 使用双引号:git branch -a | egrep "remotes/origin/${YOUR_BRANCH_NAME}$"
                    • 这不是最优的,因为即使您只匹配现有分支名称的一部分,但与目标分支不完全匹配,它也会返回 true。所以这不能在脚本中安全地用于在检查分支之前测试分支是否存在。不过还是感谢您的分享,因为我发现它很有用。可以这样修复:git branch -a | grep "\b${BRANCH}$"
                    • git fetch 如果使用 git branch -a 是必需的,因此首先获取所有远程引用。否则使用其他人指出的git ls-remote
                    • git branch -a --list '&lt;pattern&gt;'也是一个选项。如果您需要脚本的返回码,请通过管道传递给 grep。
                    【解决方案14】:

                    您可以在 Bash 终端中执行类似的操作。只需将 echos 替换为您要执行的命令即可。

                    if git ls-remote https://username:password@github.com/project-name/project-name.git | grep -sw "remote_branch_name" 2>&1>/dev/null; then echo "IT EXISTS..START MERGE" ; else echo "NOT FOUND" ; fi
                    

                    希望对你有帮助。

                    【讨论】:

                    • 我喜欢。其他答案也有ls-remote,我喜欢的是“if”。
                    【解决方案15】:

                    您可以使用git remote add something https://github.com/project-name/project-name.git 将您拥有的存储库添加为远程,然后执行git remote show something 以获取有关远程的所有信息。这需要网络连接并且对人类使用很有用。

                    或者,执行git fetch something。这将获取远程名为something 的所有分支并将它们保存在本地存储库中。然后,您可以根据需要将它们合并到您的本地分支中。我推荐这条路径,因为如果你最终决定必须合并,这就是你需要做的。

                    OT:您使用“本地签出”表示您是从集中式版本控制系统的角度来处理此问题的。当你处理 git 时,这通常是一个死胡同。它使用“结帐”等词与旧系统的使用方式不同。

                    【讨论】:

                    • 感谢您的解释。我还没有习惯 git,它确实需要不同的思维方式。
                    【解决方案16】:
                    git ls-remote --heads https://github.com/rails/rails.git
                    5b3f7563ae1b4a7160fda7fe34240d40c5777dcd    refs/heads/1-2-stable
                    81d828a14c82b882e31612431a56f830bdc1076f    refs/heads/2-0-stable
                    b5d759fd2848146f7ee7a4c1b1a4be39e2f1a2bc    refs/heads/2-1-stable
                    c6cb5a5ab00ac9e857e5b2757d2bce6a5ad14b32    refs/heads/2-2-stable
                    e0774e47302a907319ed974ccf59b8b54d32bbde    refs/heads/2-3-stable
                    13ad87971cc16ebc5c286b484821e2cb0fc3e3b1    refs/heads/3-0-stable
                    3df6c73f9edb3a99f0d51d827ef13a439f31743a    refs/heads/3-1-stable
                    f4db3d72ea564c77d5a689b850751ce510500585    refs/heads/compressor
                    c5a809e29e9213102351def7e791c3a8a67d7371    refs/heads/deps_refactor
                    821e15e5f2d9ef2aa43918a16cbd00f40c221e95    refs/heads/encoding
                    8f57bf207ff4f28fa8da4544ebc573007b65439d    refs/heads/master
                    c796d695909c8632b4074b7af69a1ef46c68289a    refs/heads/sass-cleanup
                    afd7140b66e7cb32e1be58d9e44489e6bcbde0dc    refs/heads/serializers
                    

                    【讨论】:

                    • 我也不知道 ls-remote。谢谢!
                    • 我需要在 bash 脚本中进行测试,因此只对退出代码感兴趣,所以我在本地克隆中执行了以下操作:git ls-remote --exit-code . origin/branch-name &amp;&gt; /dev/null 然后使用$? 作为测试操作数
                    • @Darren,与if git ls-remote ...; then ...; fi 一样,直接在条件中使用命令,比检查$?(可以通过记录语句、陷阱等更改)更不容易出错。
                    • 为什么是--heads
                    • @JohnLinux --heads 仅列出分支。使用--tags 仅列出标签。
                    猜你喜欢
                    • 2014-02-10
                    • 2011-03-03
                    • 1970-01-01
                    • 2012-12-31
                    • 1970-01-01
                    • 2017-04-30
                    • 2014-06-20
                    • 2016-05-11
                    • 2021-12-11
                    相关资源
                    最近更新 更多