¿Cómo comprobar si existe una rama remota en un repositorio remoto determinado?

105

Necesito hacer una fusión de subárbol para una rama específica, si existe en un repositorio remoto dado. El problema es que el repositorio remoto no está desprotegido localmente, por lo que no puedo usarlo git branch -r. Todo lo que tengo es una dirección remota, algo como esto https://github.com/project-name/project-name.git. ¿Hay alguna forma de enumerar las sucursales remotas solo por una dirección remota? No pude encontrar nada útil :(

Afilado
fuente

Respuestas:

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

En caso de que branch-namese encuentre, obtendrá el siguiente resultado:

b523c9000c4df1afbd8371324083fef218669108        refs/heads/branch-name

De lo contrario, no se enviará ninguna salida.

Así que conectarlo wcte dará 1o 0:

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

Alternativamente, puede establecer un --exit-codeindicador en el git ls-remoteque devolverá el código de salida 2en caso de que no se encuentren referencias coincidentes. Esta es la solución más idiomática. El resultado se puede verificar directamente en una prueba de shell o verificando la variable de estado $?.

$ git ls-remote --exit-code --heads  [email protected]:user/repo.git branch-name
user487772
fuente
7
He usado git ls-remote --heads ${REPO} ${BRANCH} | grep ${BRANCH} >/dev/nullseguido porif [ "$?" == "1" ] ; then echo "Branch doesn't exist"; exit; fi
sibaz
1
Estuve buscando esta respuesta limpia y precisa durante unas horas, brillante.
medik
Debe especificar el nombre de la rama como /refs/heads/branch-name. De lo contrario, la rama foo/branch-namese devolverá incluso cuando no haya branch-name.
FuzzY
Felicitaciones por su insignia dorada de "Gran respuesta". :)
jmort253
4
Nota: Si no desea tener que especificar la URL del repositorio, puede especificar el nombre remoto del repositorio, por ejemplo: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
fuente
Tampoco sabía sobre ls-remote. ¡Gracias!
Esperado
7
Necesitaba hacer una prueba en un script bash y, por lo tanto, solo estaba realmente interesado en el código de salida, así que hice lo siguiente en un clon local: git ls-remote --exit-code . origin/branch-name &> /dev/nullluego lo usé $?como operando de prueba
Darren Bishop
5
@Darren, simplemente usar el comando directamente en un condicional, como con if git ls-remote ...; then ...; fi, es menos propenso a errores que la verificación $?(que se puede cambiar mediante declaraciones de registro, trampas, etc.).
Charles Duffy
¿Por qué el --heads?
Steve
@JohnLinux --headssolo enumera las ramas. utilizar --tagspara enumerar etiquetas solamente.
Rymo
19

Otra forma que puede usar en la carpeta actual si es un repositorio git para ejecutar

git branch -a | egrep 'remotes/origin/${YOUR_BRANCH_NAME}$'
РАВИ
fuente
2
Use comillas dobles:git branch -a | egrep "remotes/origin/${YOUR_BRANCH_NAME}$"
Ivan
3
Esto no es óptimo porque devolverá verdadero incluso si solo coincidió con parte del nombre de una rama existente, pero no coincidió exactamente con la rama de destino. Por lo tanto, esto no se puede usar de manera segura en un script para probar si la rama existe antes de verificarla. Sin embargo, gracias por compartirlo, ya que lo encontré útil. Se puede arreglar así:git branch -a | grep "\b${BRANCH}$"
EntangledLoops
2
git fetches necesario si se usa git branch -apara que todas las referencias remotas se obtengan primero. De lo contrario, use git ls-remotecomo lo señalaron otros.
hIpPy
git branch -a --list '<pattern>'también es una opción. Pipe to grep si necesita un código de retorno para su script.
LOAS
17

También puedes usar esto:

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

devuelve el último compromiso y valor de $? es 0; de lo contrario, devuelve "fatal: bad sha1 reference remotes / origin / <>" y valor de $? es 128

Ajo Paul
fuente
Esto no extraerá ramas del control remoto antes de verificar, por lo que no obtendrá el último estado remoto.
siemanko
11

Entonces no es necesario pasar manualmente el nombre del repositorio cada vez.

git ls-remote origin <branch>

En vez de

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

Ejemplo:

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

O

git ls-remote origin uat_21dec

Ambos darán la misma salida:

ingrese la descripción de la imagen aquí

Más sobre Origin : Git tiene el concepto de "controles remotos", que son simplemente URL a otras copias de su repositorio. Cuando clonas otro repositorio, Git crea automáticamente un remoto llamado "origen" y lo apunta. Puede ver más información sobre el control remoto escribiendo git remote show origin.

Amitesh Bharti
fuente
11

Todas las respuestas aquí son específicas del shell de Linux, lo que no ayuda mucho si se encuentra en un entorno que no admite ese tipo de operaciones, por ejemplo, el símbolo del sistema de Windows.

Afortunadamente git ls-remoteacepta un --exit-codeargumento que devuelve 0 o 2 dependiendo de si la rama existe o no, respectivamente. Entonces:

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

devolverá 0, y

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

volverá 2.

Para PowerShell, simplemente puede usar la semántica de control de veracidad incorporada:

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

rinde $true, mientras que:

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

rendimientos $false.

Ian Kemp
fuente
10

Puede hacer algo como esto en la terminal Bash. Simplemente reemplace los ecos con los comandos que desea ejecutar.

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

Espero eso ayude.

sagunms
fuente
1
Me gusta. otras respuestas también tienen ls-remote, lo que me gusta es el "si".
Stony
6
$ git ls-remote --heads origin <branch> | wc -l

Trabaja la mayor parte del tiempo.

Pero no funcionará si la rama coincide parcialmente como se muestra a continuación,

$ git branch -a
creative/dev
qa/dev

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

Utilizar

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

si quieres una forma confiable.

Si desea usar en un script y no quiere asumir origincomo remoto predeterminado, entonces

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

Deberia trabajar.

Tenga en cuenta que git branch -a | grep ...no es confiable, ya que puede haber pasado un tiempo desde que fetchse ejecutó la última vez.

ayuda
fuente
Para mí, esta es la respuesta aceptada, combinada con la de Amitesh (nombre remoto corto), combinada con la de James Cache ( grep -x "$branch"es idéntica a grep ^"$branch"$). Aunque en los scripts que prefiero el formato largo conmuta: --line-regexp. Además, no hay necesidad de hacerlo wc -l. Poner una salida vacía en un Bash se if [ -z ] evalúa efectivamente como verdadero, por lo que significa que la rama no existe. Eso le ahorra unos milisegundos.
Amedee Van Gasse
1

Puede agregar el repositorio que tiene como un uso remoto git remote add something https://github.com/project-name/project-name.gity luego hacer una git remote show somethingpara obtener toda la información sobre el control remoto. Esto requiere una conexión de red y es útil para uso humano.

Alternativamente, haz un git fetch something. Esto buscará todas las ramas en el control remoto llamado somethingy las mantendrá en su repositorio local. Luego, puede combinarlos en su sucursal local como desee. Recomiendo este camino ya que si finalmente se decide que tiene a la fusión, esto es lo que hay que hacer.

OT: Su uso de "verificado localmente" indica que está abordando esto desde un punto de vista de sistema de control de versiones centralizado. Eso suele ser un callejón sin salida cuando se trata de git. Utiliza palabras como "pago", etc. de manera diferente a como lo hacían los sistemas más antiguos.

Noufal Ibrahim
fuente
Gracias por las explicaciones. No me acostumbré a Git todavía, y requiere una forma diferente de pensar.
Esperado
1

Puedes probar

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

Aquí se @{u}refiere a remoto / ascendente, y se @{0}refiere a HEAD local actual (con la versión más nueva de git, @{0}se puede abreviar como @). Si el control remoto no existe, se produce un error.

Con git 2.16.2 (no estoy seguro de qué versión es la primera en tener esta funcionalidad, por ejemplo, git 1.7.1 no la tiene), puede hacerlo

git checkout

Si existe una rama remota, habrá alguna salida, como

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

De lo contrario, no hay salida.

nos
fuente
1

Devolverá todas las ramas (remotas o locales) que contengan la consulta en el nombre.

git branch --all | grep <query>

alexoviedo999
fuente
0

Si los nombres de sus sucursales son muy específicos, es posible que no necesite usar grep para una simple coincidencia de nombres de sucursales:

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

que funciona para

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

Usamos un ID de problema único como nombres de sucursales y funciona bien.

Fabio
fuente
0

Acabo de intentar esto:

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

Esto devolverá 1 si se encuentra la rama "su-rama" y 0 en caso contrario.

James Cache
fuente
0

Estoy combinando algunas de las respuestas anteriores en 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

Este script obtendrá 4 ramas de un bitbucket remoto y las enviará a un github remoto, y luego enviará todas las etiquetas a github. Estoy usando esto en un trabajo de Jenkins, por eso no ve ninguno git fetcho git pull, eso ya está hecho en la configuración del repositorio de trabajos de Jenkins.

Por lo general, prefiero las opciones de formato largo en los scripts. Podría haber combinado git branchy git checkoutusando git checkout -B.

Amedee Van Gasse
fuente