git: sabe programáticamente por cuánto está la twig adelante / detrás de una twig remota

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:

  1. ¿Cómo saber la twig de seguimiento remoto? A menudo es de origin/branch pero no es necesario que lo sea.
  2. ¿Cómo get los numbers? ¿Cómo saber si está adelante / atrás? ¿Por cuántos commits? ¿Y qué hay del caso de bifurcación divergente?

actualizar

Tal como lo señala amalloy, las versiones recientes de git admiten encontrar la twig de seguimiento coincidente para una twig dada al dar "branchname @ {upstream}" (o "branchname @ {u}", o "@ {u}" para la twig 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 queue" confirma listo para empujar.

respuesta original

No parece haber una manera fácil de encontrar la twig de seguimiento en general, sin analizar muchas configuraciones de git más de lo que es práctico en algunos commands 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 count tres puntos entre $ tracking_branch y HEAD). Esto mostrará commits en ambos "arms" con una marca distintiva en el frente: "<" para commits en $ tracking_branch, y ">" para commits en HEAD.

git rev-list origin..HEAD mostrará los commits que están en su twig 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 commands muestran commits, entonces tienes twigs divergentes.

Puedes probar git branch -v -v . Con el indicador -v dado dos veces, muestra nombres de twigs 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 formatting es más estable que el resultado de git status .

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 twig actual tenía una twig 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 get 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 # inspinetworking 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.

En las versiones modernas de git, @{u} apunta al flujo ascendente de la twig actual, si hay uno configurado.

Entonces, para contar cuántos commits tienes detrás de la twig de seguimiento remoto:

 git rev-list HEAD..@{u} | wc -l 

Y para ver qué tan lejos estás del control remoto, simplemente cambia el order:

 git rev-list @{u}..HEAD | wc -l 

Para un resumen más legible, puede solicitar un logging en su lugar:

 git log --pretty=oneline @{u}..HEAD 

Para mis propios fines, estoy trabajando en una secuencia de commands que replaceá 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).

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 get 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 count 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 ).

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 get 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 repository de git-config en github . Por ejemplo, aquí está mi git-compare-upstream . Consulte el LÉAME para get instrucciones de installation y otros scripts relacionados útiles.

¿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 

¿Cómo saber la twig 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 reference a la twig a la que estás presionando. @{push} : esa sería la twig 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 twigs que están configuradas para enviar a una sucursal.

 git for-each-ref --format="%(push:track)" refs/heads 

Consulte más información en " Visualización de compromisos Git no solicitados "