remotas - git remote
git: sabe programáticamente por cuánto está la rama adelante/detrás de una rama remota (9)
Me gustaría extraer la información que se imprime después de un git status
, que se ve así:
# On branch master
# Your branch is ahead of ''origin/master'' by 2 commits.
Por supuesto, puedo analizar el resultado del git status
de git status
pero esto no se recomienda, ya que esta salida legible para humanos puede cambiar.
Hay dos problemas:
- ¿Cómo saber la rama de seguimiento remoto? A menudo es de
origin/branch
pero no es necesario que lo sea. - ¿Cómo obtener los números? ¿Cómo saber si está adelante / atrás? ¿Por cuántos commits? ¿Y qué hay del caso de bifurcación divergente?
¿Cómo saber la rama de seguimiento remoto? A menudo es de
origin/branch
pero no es necesario que lo sea.
Git 2.5+ introduce un nuevo atajo que hace referencia a la rama a la que estás presionando. @{push}
: esa sería la rama de seguimiento remoto que es de interés aquí.
Eso significa que tiene otra opción para ver hacia adelante / atrás para todas las ramas que están configuradas para enviar a una sucursal.
git for-each-ref --format="%(push:track)" refs/heads
Ver más en " Visualización de Compromisos de Git no empujados "
¿Por qué esto no funcionaría?
#!/bin/sh
git diff origin/master..HEAD --quiet --exit-code
RETVAL=$?
if [ $RETVAL -gt 0 ]; then
echo "You need to git push!"
else
echo "No git push necessary!"
fi
En las versiones modernas de git, @{u}
apunta al flujo ascendente de la rama actual, si hay uno configurado.
Entonces, para contar cuántos commits tienes detrás de la rama de seguimiento remoto:
git rev-list HEAD..@{u} | wc -l
Y para ver qué tan lejos estás del control remoto, simplemente cambia el orden:
git rev-list @{u}..HEAD | wc -l
Para un resumen más legible, puede solicitar un registro en su lugar:
git log --pretty=oneline @{u}..HEAD
Para mis propios fines, estoy trabajando en una secuencia de comandos que reemplazará a @{u}
con una conjetura adecuada, si aún no se ha establecido el flujo ascendente. Desafortunadamente, en este momento no hay @{d}
para representar el flujo descendente (a donde presionarías).
La parte superior del código en la respuesta de araqnid no funciona para mí, así que tal vez algo en git ha cambiado desde que fue escrito hace 18 meses. Funciona si cambio:
tracking_branch=refs/remotes/$remote/$remote_branch
a
tracking_branch=$remote/$remote_branch
Sin embargo, todavía existe un problema al rastrear una sucursal local, en cuyo caso debe recortar la parte remota (que se convierte en ''.''):
tracking_branch=${tracking_branch#./}
Luego puede obtener programáticamente el número de revisiones detrás y adelante de la siguiente manera:
set -- `git rev-list --left-right --count $tracking_branch...HEAD`
behind="$1"
ahead="$2"
He escrito guiones para hacer todo eso (y más, por ejemplo, también pueden intentar localizar controles remotos al otro lado de un puente de git-svn), y los publiqué en mi repositorio de git-config en github . Por ejemplo, aquí está mi git-compare-upstream . Consulte el LÉAME para obtener instrucciones de instalación y otros scripts relacionados útiles.
Puedes probar git branch -v -v
. Con el indicador -v
dado dos veces, muestra nombres de ramas ascendentes. Muestra de salida:
* devel 7a5ff2c [origin/devel: ahead 1] smaller file status overlay icons
master 37ca389 [origin/master] initial project check-in.
Creo que este formato es más estable que el resultado de git status
.
git rev-list origin..HEAD
mostrará los commits que están en su rama actual, pero no de origen, es decir, si está por delante del origen y por cuál commits.
git rev-list HEAD..origin
mostrará lo opuesto.
Si ambos comandos muestran commits, entonces tienes ramas divergentes.
git status
tiene una opción --porcelain
que está destinada a analizar mediante scripts. Se basa en la salida --short
- son casi idénticos en el momento de la escritura (consulte la sección "Formato de porcelana" de la página del manual de estado de git para obtener más información). La principal diferencia es que --short
tiene salida de color.
Por defecto, no se muestra información de bifurcación, pero si agrega la opción --branch
obtendrá resultados como:
git status --short --branch
## master...origin/master [ahead 1]
?? untrackedfile.txt
...
Si está actualizado (después de una búsqueda), la línea de bifurcación será:
## master
Si estás adelante:
## master...origin/master [ahead 1]
Si estás detrás:
## master...origin/master [behind 58]
Y para ambos:
## master...origin/master [ahead 1, behind 58]
Tenga en cuenta que el git status --porcelain --branch
solo está disponible en 1.7.10.3 o posterior (aunque el git status --short --branch
ha estado disponible desde 1.7.2 ).
Editar: Mi respuesta original en realidad no era muy buena porque dependía del usuario para tener un control remoto llamado "origen". También falló si la rama actual tenía una rama de rastreo además del origen-jefe. Estos defectos esencialmente lo hicieron inútil. Sin embargo, la respuesta de @araqnid no es el método más eficiente y la forma en que llega a $tracking_branch
es menor que el estrecho. El método más eficiente (más rápido) que he encontrado para obtener la misma funcionalidad es el siguiente:
# get the tracking-branch name
tracking_branch=$(git for-each-ref --format=''%(upstream:short)'' $(git symbolic-ref -q HEAD))
# creates global variables $1 and $2 based on left vs. right tracking
# inspired by @adam_spiers
set -- $(git rev-list --left-right --count $tracking_branch...HEAD)
behind=$1
ahead=$2
respuesta original: (inferior, pero dada por claridad)
Tal vez el método más simple que pude encontrar (inspirado en @insidepower)
# count the number of logs
behind=$(git log --oneline HEAD..origin | wc -l)
ahead=$( git log --oneline origin..HEAD | wc -l)
Anteriormente había estado usando el método de @araqnid, pero ahora creo que moveré algunos de mis scripts a este método, ya que es mucho más simple. Esto debería funcionar en cualquier sistema Unix.
actualizar
Tal como lo señala amalloy, las versiones recientes de git admiten la búsqueda de la rama de seguimiento coincidente para una rama dada al dar "branchname @ {upstream}" (o "branchname @ {u}", o "@ {u}" para la rama de seguimiento de HEAD). Esto efectivamente reemplaza el script a continuación. Tu puedes hacer:
git rev-list @{u}..
git rev-list --left-right --boundary @{u}...
gitk @{u}...
etc. Por ejemplo, tengo git q
aliased para git log --pretty=''...'' @{u}..
para mostrarme que "en cola" confirma listo para empujar.
respuesta original
No parece haber una manera fácil de encontrar la rama de seguimiento en general, sin analizar muchas configuraciones de git más de lo que es práctico en algunos comandos de shell. Pero en muchos casos esto será muy útil:
# work out the current branch name
currentbranch=$(expr $(git symbolic-ref HEAD) : ''refs/heads//(.*/)'')
[ -n "$currentbranch" ] || die "You don''t seem to be on a branch"
# look up this branch in the configuration
remote=$(git config branch.$currentbranch.remote)
remote_ref=$(git config branch.$currentbranch.merge)
# convert the remote ref into the tracking ref... this is a hack
remote_branch=$(expr $remote_ref : ''refs/heads//(.*/)'')
tracking_branch=refs/remotes/$remote/$remote_branch
# now $tracking_branch should be the local ref tracking HEAD
git rev-list $tracking_branch..HEAD
Otro enfoque más de fuerza bruta:
git rev-list HEAD --not --remotes
La respuesta de jamessan explica cómo encontrar las diferencias relativas entre $ tracking_branch y HEAD usando git rev-list
. Una cosa divertida que puedes hacer:
git rev-list --left-right $tracking_branch...HEAD
(tenga en cuenta tres puntos entre $ tracking_branch y HEAD). Esto mostrará commits en ambos "brazos" con una marca distintiva en el frente: "<" para commits en $ tracking_branch, y ">" para commits en HEAD.