Как проверить, существует ли удаленная ветка в данном удаленном репозитории?

106

Мне нужно выполнить слияние поддерева для конкретной ветки, если она существует в данном удаленном репозитории. Проблема в том, что удаленный репозиторий не извлечен локально, поэтому я не могу его использовать git branch -r. Все, что у меня есть, это удаленный адрес, что-то вроде этого https://github.com/project-name/project-name.git. Есть ли способ перечислить удаленные ветки только по удаленному адресу? Ничего полезного не нашел :(

Острый
источник

Ответы:

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

В случае branch-nameобнаружения вы получите следующий результат:

b523c9000c4df1afbd8371324083fef218669108        refs/heads/branch-name

В противном случае вывод не будет отправлен.

Таким образом, подключение к нему wcдаст вам 1или 0:

$ 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
user487772
источник
7
Я использовал git ls-remote --heads ${REPO} ${BRANCH} | grep ${BRANCH} >/dev/nullfollowed byif [ "$?" == "1" ] ; then echo "Branch doesn't exist"; exit; fi
sibaz
1
Я искал этот аккуратный и точный ответ несколько часов, блестяще.
medik 05
Вам нужно указать название ветки как /refs/heads/branch-name. В противном случае ветвь foo/branch-nameбудет возвращена, даже если нет branch-name.
FuzzY
Поздравляем с получением золотого значка «Отличный ответ». :)
jmort253 09
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затем использовал $?в качестве тестового операнда
Даррен Бишоп
5
@Darren, просто используя команду непосредственно в условном выражении, как и в случае, if git ls-remote ...; then ...; fiменее подвержен ошибкам, чем проверка $?(которую можно изменить с помощью операторов регистрации, ловушек и т. Д.).
Чарльз Даффи
Почему --heads?
Стив
@JohnLinux --headsперечисляет только ветки. используйте только --tagsдля перечисления тегов.
rymo
19

Другой способ, который вы можете использовать в текущей папке, если это репозиторий git для запуска

git branch -a | egrep 'remotes/origin/${YOUR_BRANCH_NAME}$'
РАВИ
источник
2
Используйте двойные кавычки:git branch -a | egrep "remotes/origin/${YOUR_BRANCH_NAME}$"
Иван,
3
Это не оптимально, потому что он вернет истину, даже если вы сопоставили только часть имени существующей ветки, но не совсем точно соответствовали целевой ветке. Таким образом, это нельзя безопасно использовать в сценарии для проверки существования ветки перед ее проверкой. Тем не менее, спасибо, что поделились, так как я нашел это полезным. Можно исправить вот так:git branch -a | grep "\b${BRANCH}$"
EntangledLoops
2
git fetchтребуется при использовании, git branch -aпоэтому сначала выбираются все ссылки на удаленные устройства. Другое использование, git ls-remoteкак указано другими.
hIpPy 06
git branch -a --list '<pattern>'тоже вариант. Вернитесь к grep, если вам нужен код возврата для вашего скрипта.
LOAS 03
16

Вы также можете использовать это:

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

возвращает последнюю фиксацию и значение $? равно 0, в противном случае возвращается "fatal: bad sha1 reference remotes / origin / <>" и значение $? 128

Аджо Пол
источник
1
Это не будет извлекать ветки с удаленного компьютера перед проверкой, поэтому вы не получите последнее удаленное состояние.
siemanko 09
12

Все ответы здесь относятся к оболочке Linux, что не очень помогает, если вы находитесь в среде, которая не поддерживает такие операции - например, в командной строке 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.

Ян Кемп
источник
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, мне нравится «если».
Stony
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

Оба дадут одинаковый результат:

введите описание изображения здесь

Подробнее об Origin : Git использует понятие «удаленных», которые представляют собой просто URL-адреса других копий вашего репозитория. Когда вы клонируете другой репозиторий, Git автоматически создает удаленный объект с именем «origin» и указывает на него. Вы можете увидеть дополнительную информацию об пульте дистанционного управления, набрав git remote show origin.

Амитеш Бхарти
источник
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 ] эффективно оценивается как истинное, поэтому это означает, что ветка не существует. Это сэкономит вам несколько миллисекунд.
Амеди Ван Гассе
1

Вы можете добавить репозиторий, который у вас есть как удаленный, git remote add something https://github.com/project-name/project-name.gitа затем выполнитьgit remote show something чтобы получить всю информацию о пульте. Это требует подключения к сети и полезно для использования человеком.

В качестве альтернативы выполните файл git fetch something. Это приведет к извлечению всех веток на вызываемом удаленном компьютере somethingи сохранит их в вашем локальном репозитории. Затем вы можете объединить их в свой локальный филиал по своему усмотрению. Я рекомендую этот путь, поскольку, если вы наконец решите, что вам нужно выполнить слияние, это то, что вам нужно сделать.

ОТ: Использование вами выражения «извлечено локально» указывает на то, что вы подходите к этому с точки зрения централизованной системы контроля версий. Обычно это тупик, когда вы имеете дело с git. В нем используются такие слова, как «касса» и т. Д., Иначе, чем в старых системах.

Нуфаль Ибрагим
источник
Спасибо за объяснения. Я еще не привык к 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>

Alexoviedo999
источник
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

Мы используем уникальный идентификатор проблемы в качестве имен веток, и он отлично работает.

Фабио
источник
0

Я только что попробовал:

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

Это вернет 1, если будет найдена ветка «your-branch», и 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

Этот скрипт получит 4 ветки из удаленного битбакета и отправит их на удаленный github, а затем отправит все теги в github. Я использую это в работе Дженкинс, поэтому вы не видите какой - либо git fetchилиgit pull , это уже сделано в конфигурации репозитория заданий Jenkins.

Я обычно предпочитаю длинные варианты в скриптах. Я мог бы совместить git branchи git checkoutс помощью git checkout -B.

Амеди Ван Гассе
источник