Comment vérifier si une branche distante existe sur un référentiel distant donné?

106

Je dois effectuer une fusion de sous-arborescence pour une branche spécifique, si elle existe sur un référentiel distant donné. Le problème est que le référentiel distant n'est pas extrait localement, donc je ne peux pas l'utiliser git branch -r. Tout ce que j'ai, c'est une adresse distante, quelque chose comme ça https://github.com/project-name/project-name.git. Existe-t-il un moyen de répertorier les succursales distantes uniquement par une adresse distante? Je n'ai rien trouvé d'utile :(

Enthousiaste
la source

Réponses:

124
$ git ls-remote --heads [email protected]:user/repo.git branch-name

Dans le cas où branch-namese trouve vous obtiendrez le résultat suivant:

b523c9000c4df1afbd8371324083fef218669108        refs/heads/branch-name

Sinon, aucune sortie ne sera envoyée.

Donc, le faire wcpasser vous donnera 1ou 0:

$ git ls-remote --heads [email protected]:user/repo.git branch-name | wc -l

Vous pouvez également définir un --exit-codeindicateur sur git ls-remotelequel retournera le code de sortie 2au cas où aucune référence correspondante ne serait trouvée. C'est la solution la plus idiomatique. Le résultat peut être vérifié directement dans un test shell ou en vérifiant la variable status $?.

$ git ls-remote --exit-code --heads  [email protected]:user/repo.git branch-name
user487772
la source
7
J'ai utilisé git ls-remote --heads ${REPO} ${BRANCH} | grep ${BRANCH} >/dev/nullsuivi deif [ "$?" == "1" ] ; then echo "Branch doesn't exist"; exit; fi
sibaz
1
Je cherchais cette réponse nette et précise pendant quelques heures, géniale.
medik
Vous devez spécifier le nom de la branche sous la forme /refs/heads/branch-name. Sinon, la branche foo/branch-nameserait retournée même s'il n'y a pas branch-name.
FuzzY
Félicitations pour votre badge doré «Great Answer». :)
jmort253
4
Remarque: Si vous ne voulez pas avoir à spécifier l'URL du dépôt, vous pouvez spécifier le nom du dépôt distant à la place, par exemple: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
Dogbert
la source
Je ne savais pas non plus sur ls-remote. Je vous remercie!
Keen
7
J'avais besoin de faire un test dans un script bash et je n'étais donc vraiment intéressé que par le code de sortie, alors j'ai fait ce qui suit dans un clone local: git ls-remote --exit-code . origin/branch-name &> /dev/nullpuis utilisé $?comme opérande de test
Darren Bishop
5
@Darren, simplement utiliser la commande directement dans un conditionnel, comme avec if git ls-remote ...; then ...; fi, est moins sujet aux erreurs que la vérification $?(qui peut être modifiée en enregistrant des instructions, des interruptions, etc.).
Charles Duffy
Pourquoi le --heads?
Steve
@JohnLinux --headsrépertorie uniquement les branches. utiliser --tagspour lister uniquement les balises.
rymo
19

Une autre façon que vous pouvez utiliser dans le dossier actuel s'il s'agit d'un dépôt git à exécuter

git branch -a | egrep 'remotes/origin/${YOUR_BRANCH_NAME}$'
РАВИ
la source
2
Utilisez des guillemets doubles:git branch -a | egrep "remotes/origin/${YOUR_BRANCH_NAME}$"
Ivan
3
Ce n'est pas optimal car il retournera true même si vous ne correspondiez qu'à une partie d'un nom de branche existant, mais que vous ne correspondiez pas exactement à la branche cible. Cela ne peut donc pas être utilisé en toute sécurité dans un script pour tester si la branche existe avant de la récupérer. Merci de partager quand même, car je l'ai trouvé utile. Peut être corrigé comme ceci:git branch -a | grep "\b${BRANCH}$"
EntangledLoops
2
git fetchest requis si vous utilisez git branch -apour que toutes les références des télécommandes soient récupérées en premier. Sinon, utilisez git ls-remotecomme indiqué par d'autres.
hIpPy
git branch -a --list '<pattern>'est également une option. Dirigez vers grep si vous avez besoin d'un code de retour pour votre script.
LOAS
17

Vous pouvez également utiliser ceci:

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

renvoie le dernier commit et la valeur de $? vaut 0 sinon renvoie "fatal: bad sha1 reference remotes / origin / <>" et la valeur de $? est 128

Ajo Paul
la source
Cela ne tirera pas les branches de la télécommande avant la vérification, vous n'obtiendrez donc pas le dernier état distant.
siemanko
11

Vous pouvez faire quelque chose comme ça dans le terminal Bash. Remplacez simplement les échos par les commandes que vous souhaitez exécuter.

if git ls-remote https://username:[email protected]/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

J'espère que ça aide.

sagunms
la source
1
Je l'aime. d'autres réponses ont aussi ls-remote, ce que j'aime c'est le "si".
Stony
11

Alors inutile de passer manuellement le nom du référentiel à chaque fois.

git ls-remote origin <branch>

Au lieu de

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

Exemple :

git ls-remote [email protected]:landmarkgroupme/in-store-application.git  uat_21dec

OU

git ls-remote origin uat_21dec

Les deux donneront le même résultat:

entrez la description de l'image ici

Plus d'informations sur Origin : Git a le concept de "télécommandes", qui sont simplement des URL vers d'autres copies de votre référentiel. Lorsque vous clonez un autre dépôt, Git crée automatiquement une télécommande nommée "origin" et pointe vers elle. Vous pouvez voir plus d'informations sur la télécommande en tapant git remote show origin.

Amitesh Bharti
la source
11

Toutes les réponses ici sont spécifiques au shell Linux, ce qui n'aide pas beaucoup si vous êtes dans un environnement qui ne prend pas en charge ce type d'opérations - par exemple, l'invite de commande de Windows.

git ls-remoteAccepte heureusement un --exit-codeargument qui renvoie 0 ou 2 selon que la branche existe ou non, respectivement. Alors:

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

renverra 0, et

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

retournera 2.

Pour PowerShell, vous pouvez simplement utiliser la sémantique intégrée de gestion de la vérité:

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

donne $true, tandis que:

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

rendements $false.

Ian Kemp
la source
6
$ git ls-remote --heads origin <branch> | wc -l

Fonctionne la plupart du temps.

Mais ne fonctionnera pas si la branche correspond partiellement comme ci-dessous,

$ git branch -a
creative/dev
qa/dev

$ git ls-remote --heads origin dev | wc -l
2

Utilisation

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

si vous voulez un moyen fiable.

Si vous souhaitez utiliser dans le script et ne voulez pas assumer origincomme télécommande par défaut, alors

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

devrait marcher.

Notez que ce git branch -a | grep ...n'est pas fiable car il peut fetchs'écouler un certain temps depuis la dernière exécution.

hippie
la source
Pour moi, c'est la réponse acceptée, combinée à celle d'Amitesh (nom abrégé de la télécommande), combinée à celle de James Cache ( grep -x "$branch"est identique à grep ^"$branch"$). Bien que dans les scripts que je préfère la forme longue passe: --line-regexp. En outre, il n'est pas nécessaire de le faire wc -l. Mettre une sortie vide dans un Bash est if [ -z ] effectivement évalué comme vrai, ce qui signifie que la branche n'existe pas. Cela vous fait gagner quelques millisecondes.
Amedee Van Gasse le
1

Vous pouvez ajouter le référentiel que vous avez en tant que télécommande à l'aide git remote add something https://github.com/project-name/project-name.git, puis effectuer ungit remote show something pour obtenir toutes les informations sur la télécommande. Cela nécessite une connexion réseau et est utile pour un usage humain.

Sinon, faites un git fetch something. Cela récupérera toutes les branches de la télécommande appelée somethinget les conservera dans votre référentiel local. Vous pouvez ensuite les fusionner dans votre succursale locale à votre guise. Je recommande ce chemin car si vous décidez enfin que vous devez fusionner, c'est ce que vous devez faire.

OT: Votre utilisation de «extrait localement» indique que vous abordez cela du point de vue d'un système de contrôle de version centralisé. C'est généralement une impasse lorsque vous avez affaire à git. Il utilise des mots comme «checkout», etc. différemment de la façon dont les anciens systèmes le faisaient.

Noufal Ibrahim
la source
Merci pour les explications. Je ne me suis pas encore habitué à git, et cela nécessite une manière de penser différente.
Keen
1

Tu peux essayer

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

Ici se @{u}réfère à remote / upstream, et se @{0}réfère à HEAD local actuel (avec une version plus récente de git, @{0}peut être raccourci comme @). Si la télécommande n'existe pas, il se trompe.

Avec git 2.16.2 (je ne sais pas quelle version est la première à avoir cette fonctionnalité, par exemple, git 1.7.1 ne l'a pas), vous pouvez faire

git checkout

Si une branche distante existe, il y aura une sortie, comme

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

Sinon, il n'y a pas de sortie.

nos
la source
1

Renvoie toutes les branches (distantes ou locales) qui contiennent la requête dans le nom.

git branch --all | grep <query>

alexoviedo999
la source
0

Si vos noms de branche sont très spécifiques, vous n'aurez peut-être pas besoin d'utiliser grep pour une simple correspondance de nom de branche:

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

qui fonctionne pour

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

Nous utilisons un identifiant de problème unique comme noms de branche et cela fonctionne très bien.

Fabio
la source
0

J'ai juste essayé ceci:

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

Cela renverra 1 si la branche "your-branch" est trouvée et 0 sinon.

James Cache
la source
0

Je combine certaines des réponses ci-dessus dans un script:

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

Ce script obtiendra 4 branches à partir d'un bitbucket distant, et les poussera vers un github distant, puis poussera toutes les balises vers github. J'utilise ceci dans un travail Jenkins, c'est pourquoi vous n'en voyez pas git fetchougit pull , c'est déjà fait dans la configuration du référentiel de travaux Jenkins.

Je préfère généralement les options longues dans les scripts. J'aurais pu combiner git branchet git checkouten utilisant git checkout -B.

Amédée Van Gasse
la source