¿Cómo puedo ver qué ramas de Git están rastreando qué rama remota / aguas arriba?

Respuestas:

1146

Muy un comando de porcelana, no es bueno si quieres esto para scripting:

git branch -vv   # doubly verbose!

Tenga en cuenta que con git 1.8.3, esa rama ascendente se muestra en azul (consulte " ¿Qué es el seguimiento de esta rama (si hay algo) en git? ")


Si desea una salida limpia, vea la respuesta de arcresu : utiliza un comando de porcelana que no creo que existiera en el momento en que escribí originalmente esta respuesta, por lo que es un poco más conciso y funciona con ramas configuradas para rebase, no solo fusión.

Cascabel
fuente
3
El primer método anterior no proporciona la información deseada para mí. El segundo ... parece excesivo, especialmente porque la respuesta de Kubi funciona. ¿Me estoy perdiendo de algo?
garyp
3
@garyp No eres el que hizo la pregunta. El primero proporcionó lo que el OP necesitaba, y el segundo proporcionó exactamente lo que necesitaba, en caso de que lo quisiera en una forma limpia para las secuencias de comandos, o simplemente quisiera guardarlo como un alias. ("Overkill" está bien si te da lo que quieres y no tienes que repetirlo). Desde el punto de vista de esta pregunta, la respuesta de Kubi proporciona información extraña, y si hay más de un control remoto, no No muestre todo, pero si satisface sus necesidades, utilícelo por todos los medios.
Cascabel
2
Debo disculpas. Cuando me encontré con un principio el primer método, me dieron ninguna información sobre lo que analiza lo que, y debería haber declarado que de forma explícita. Pero ahora veo la información de seguimiento, así que debo haber tenido algo mal con mi configuración. Así que me estaba perdiendo algo.
garyp
2
FWIW Estaba confundido porque -v y -vv muestran resultados similares. La rama rastreada se muestra entre corchetes después del hash y antes de la confirmación más reciente (en mi instalación predeterminada de OSX homebrew).
jerclarke
3
Todo lo que esto hace por mí es imprimir el último hash de confirmación y comentar para cada rama.
carpincho
263

git remote show origin

Reemplace 'origen' con el nombre de su control remoto.

kubi
fuente
11
A pesar de que este comando de porcelana funciona para un ser humano (no tanto para un script, ya que tendría que analizar la salida de porcelana), lo que no me gusta de este enfoque es que ese git remote showcomando realmente se conecta al repositorio remoto ... y por lo tanto se produce un error si le toca estar fuera de línea o no puede conectar con el repositorio por cualquier razón ...
pvandenberk
17
@pvandenberk Puede usar git remote show -n originpara obtener información incluso cuando está desconectado. De la documentación de git remote : "Con la opción -n, los cabezales remotos no se consultan primero con git ls-remote <nombre>; en su lugar, se usa la información en caché".
Cerran
55
Una cosa extraña sobre este comando: enumera las ramas remotas como "rastreadas", incluso si no hay una rama local configurada para pull / push. Siempre encuentro esto confuso. En realidad, no tengo claro qué se supone que significa "rastreado" en este resultado. Los documentos de Git sobre el tema hacen que parezca que una rama remota se "rastrea" solo cuando está vinculada / vinculada a una rama local para empujar / tirar ...
Hawkeye Parker
El problema es que necesito llamar a esto para todos los nombres remotos hasta que vea lo que realmente estoy buscando.
jolvi
2
@jolvi Puede ejecutar git remote show | xargs git remote show -npara ver información de seguimiento combinada para todos los controles remotos.
Synoli
107

Si observa la página de manual git-rev-parse, verá que se describe la siguiente sintaxis:

<branchname>@{upstream}, Por ejemplo master@{upstream},@{u}

El sufijo @{upstream}de un nombre de rama (forma abreviada <branchname>@{u}) se refiere a la rama que la rama especificada por nombre de rama está configurada para construir encima. Un nombre de rama que falta es el predeterminado.

Por lo tanto, para encontrar el flujo ascendente de la rama master, haría:

git rev-parse --abbrev-ref master@{upstream}
# => origin/master

Para imprimir la información de cada rama, puede hacer algo como:

while read branch; do
  upstream=$(git rev-parse --abbrev-ref $branch@{upstream} 2>/dev/null)
  if [[ $? == 0 ]]; then
    echo $branch tracks $upstream
  else
    echo $branch has no upstream configured
  fi
done < <(git for-each-ref --format='%(refname:short)' refs/heads/*)

# Output:
# master tracks origin/master
# ...

Esto es más limpio que analizar referencias y configuraciones manualmente.

Carl Suster
fuente
No pude entender esa parte en el análisis a pesar de encontrarlo, así que gracias por la explicación clara.
Alice Purcell
3
Para aquellos de nosotros que usamos git-flow, con ramas llamadas "feature / blahblah", la declaración de cierre del ciclo while debería leer: done < <(git for-each-ref --format='%(refname:short)' refs/heads/**)Tenga en cuenta los dos asteriscos al final del patrón global.
markeissler
2
git rev-parse --abbrev-ref HEAD@{upstream}parece funcionar bien para la rama actual. También es un buen alias de git.
Digikata
La whilesintaxis del bucle me parece un poco extraña. Puede usar el git for-each-ref ... | while read branch; do ...que no necesita un FIFO y se ejecuta en el mismo orden que los comandos escritos.
Daniel Böhmer
Al menos desde git 2.5.1, tienes una línea congit for-each-ref --format='%(refname:short) tracks %(upstream:short)' refs/heads/*
Mat M
81

Una alternativa a la respuesta de kubi es echar un vistazo al .git/configarchivo que muestra la configuración del repositorio local:

cat .git/config

Abizern
fuente
66
También git config --get-regex branch
Tamir Daniely
66
O, más específicamente, 'git config --get-regexp branch. * Merge'
yoyo
41
git for-each-ref --format='%(refname:short) <- %(upstream:short)' refs/heads

mostrará una línea para cada sucursal local. Una rama de seguimiento se verá así:

master <- origin/master

Una que no sea de seguimiento se verá así:

test <- 
Aurelien
fuente
Agradable, para agregar algunos pedidos y salida de TAB-bed: git for-each-ref --sort upstream --format = '% (refname: short)% 09 <-% (upstream: short)'
refs
Bellamente conciso y el resultado es en realidad mucho más legible que el aceptado git branch -vv. 🙏
joki
El único problema es que no puedo recordar esto, así que solíagit config --global alias.track 'for-each-ref --format='\''%(refname:short) <- %(upstream:short)'\'' refs/heads'
joki
38

Para la rama actual , aquí hay dos buenas opciones:

% git rev-parse --abbrev-ref --symbolic-full-name @{u}
origin/mainline

o

% git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)
origin/mainline

Esa respuesta también está aquí , a una pregunta ligeramente diferente que fue marcada (erróneamente) como un duplicado.

cdunn2001
fuente
55
Basado en esto, todas las ramas se pueden enumerar de una manera amigable guión: git for-each-ref --shell --format='%(refname:short) %(upstream:short)' refs/heads.
Daniel James
15

Para la rama actual, también podría decir git checkout(sin ninguna rama). Este es un no-op con efectos secundarios para mostrar la información de seguimiento, si existe, para la rama actual.

$ git checkout 
Your branch is up-to-date with 'origin/master'.
Eugene Yarmash
fuente
Es justo, pero puede escribir accidentalmente git checkout ., lo que no es un no-op.
Tomasz Gandor
6

Yo uso este alias

git config --global alias.track '!f() { ([ $# -eq 2 ] && ( echo "Setting tracking for branch " $1 " -> " $2;git branch --set-upstream $1 $2; ) || ( git for-each-ref --format="local: %(refname:short) <--sync--> remote: %(upstream:short)" refs/heads && echo --Remotes && git remote -v)); }; f'

entonces

git track
Olivier Refalo
fuente
55
Creo que vale la pena señalar que con dos parámetros su comando configura una rama de seguimiento.
albfan
3

Basado en la respuesta de Olivier Refalo

if [ $# -eq 2 ] 
then
    echo "Setting tracking for branch " $1 " -> " $2
    git branch --set-upstream $1 $2
else
    echo "-- Local --" 
    git for-each-ref --shell --format="[ %(upstream:short) != '' ] && echo -e '\t%(refname:short) <--> %(upstream:short)'" refs/heads | sh
    echo "-- Remote --" 
    REMOTES=$(git remote -v) 
    if [ "$REMOTES" != '' ]
    then
        echo $REMOTES
    fi  
fi

Muestra solo local con la pista configurada.

Escríbalo en un script llamado git-track en su ruta y obtendrá un comando git track

Una versión más elaborada en https://github.com/albfan/git-showupstream

albfan
fuente
1

git config --get-regexp "branch\.$current_branch\.remote"

le dará el nombre del control remoto que se está rastreando

git config --get-regexp "branch\.$current_branch\.merge"

le dará el nombre de la rama remota que se está rastreando.

Deberá reemplazar $ current_branch con el nombre de su sucursal actual. Puede obtener eso dinámicamente congit rev-parse --abbrev-ref HEAD

El siguiente mini script combina esas cosas. Péguelo en un archivo llamado git-tracking, hágalo ejecutable y asegúrese de que esté en su camino.

entonces puedes decir

$ git  tracking
<current_branch_name>-><remote_repo_name>/<remote_branch_name>

tenga en cuenta que el nombre de la sucursal remota puede ser diferente del nombre de su sucursal local (aunque generalmente no lo es). Por ejemplo:

$git tracking 
xxx_xls_xslx_thing -> origin/totally_bogus

Como puede ver en el código, la clave para esto es extraer los datos de la configuración de git. Solo uso sed para borrar los datos extraños.

#!/bin/sh

current_branch=$(git rev-parse --abbrev-ref HEAD)
remote=$(git config --get-regexp "branch\.$current_branch\.remote" | sed -e "s/^.* //")
remote_branch=$(git config --get-regexp "branch\.$current_branch\.merge" | \
  sed -e "s/^.* //" -e "s/refs\/.*\///")

echo "$current_branch -> $remote/$remote_branch"
masukomi
fuente
1

Aquí hay uno simple y ordenado. Puede verificar git remote -v, que le muestra todo el origen y el flujo ascendente de la rama actual.

MJeremy
fuente