如何检查给定的远程存储库上是否存在远程分支?


106

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

Answers:


124
$ 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

另外,您可以设置--exit-code标志,如果找不到匹配的引用git ls-remote,将在该标志上返回退出代码2。这是最惯用的解决方案。可以直接在外壳测试中检查结果,也可以通过检查状态变量来检查结果$?

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

7
我使用git ls-remote --heads ${REPO} ${BRANCH} | grep ${BRANCH} >/dev/null过以下方法if [ "$?" == "1" ] ; then echo "Branch doesn't exist"; exit; fi
sibaz '16

1
我一直在寻找这个简洁,准确的答案,好几个小时。
medik '17

您需要将分支名称指定为/refs/heads/branch-name。否则,foo/branch-name即使没有分支也将返回分支branch-name
模糊的

恭喜您获得“ Great Answer”金牌。:)
jmort253 '19

4
注意:如果您不想指定回购URL,则可以改为指定回购远程名称,例如:git ls-remote --heads origin branch-name
daveruinseverything

50
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。谢谢!
Keen

7
我需要在bash脚本中进行测试,因此只对退出代码非常感兴趣,因此我在本地克隆中执行了以下操作:git ls-remote --exit-code . origin/branch-name &> /dev/null然后用作$?测试操作数
Darren Bishop

5
@Darren,与一样,仅在有条件的情况下直接使用该命令if git ls-remote ...; then ...; fi比检查$?要容易出错(可以通过记录语句,陷阱等来更改)。
2014年

为什么--heads呢?
史蒂夫(Steve)

@JohnLinux --heads仅列出分支。用于--tags仅列出标签。
rymo '16

19

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

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

2
使用双引号:git branch -a | egrep "remotes/origin/${YOUR_BRANCH_NAME}$"
Ivan

3
这不是最佳选择,因为即使您仅匹配现有分支名称的一部分,但不完全匹配目标分支,它也会返回true。因此,在签出分支之前,不能在脚本中安全地使用它来测试分支是否存在。不过还是感谢您分享,因为我发现它很有用。可以这样修复:git branch -a | grep "\b${BRANCH}$"
EntangledLoops

2
git fetch如果使用则是必需的,git branch -a因此首先获取所有远程引用。其他git ls-remote人指出的其他用途。
2015年

git branch -a --list '<pattern>'也是一种选择。如果需要脚本的返回码,则通过管道传递到grep。
LOAS

17

您还可以使用以下命令:

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

返回最新的提交和$的值?为0,否则返回“致命:sha1引用远程/原点/ <>错误”和$的值?是128


这不会在检查之前从远程拉分支,因此您不会获得最新的远程状态。
siemanko

11

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

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

希望能帮助到你。


1
我喜欢。其他答案也有ls-remote,我喜欢的是“ if”。
斯托尼

11

然后,无需每次手动传递存储库名称。

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查看有关远程的更多信息。


11

这里的所有答案都是特定于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


6
$ 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,这意味着该分支不存在。这样可以节省您几毫秒的时间。
阿米德·范·加斯

1

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

或者,执行git fetch something。这将获取被调用的远程站点上的所有分支,something并将其保留在本地存储库中。然后,您可以根据需要将它们合并到本地分支中。我建议使用此路径,因为如果您最终决定必须合并,这就是您需要执行的操作。

OT:您使用“本地签出”表示从集中版本控制系统的角度来解决这个问题。当您处理git时,这通常是死路一条。它使用诸如“ checkout”等之类的词与旧系统的方式有所不同。


感谢您的解释。我还没有习惯git,它确实需要不同的思维方式。
Keen

1

你可以试试

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'

否则没有输出。


1

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

git branch --all | grep <query>


0

如果您的分支名称非常具体,则可能不需要使用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作为分支名称,并且效果很好。


0

我只是试过这个:

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

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


0

我在脚本中结合了上面的一些答案:

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作业中使用了此功能,这就是为什么您在Jenkins作业存储库配置中看不到任何git fetch或的原因git pull

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.