Pregunta Verifica si se necesita tracción en Git


¿Cómo verifico si el repositorio remoto ha cambiado y necesito extraerlo?

Ahora uso este script simple:

git pull --dry-run | grep -q -v 'Already up-to-date.' && changed=1

Pero es bastante pesado.

¿Hay una mejor manera? La solución ideal verificaría todas las ramas remotas y devolvería los nombres de las ramas modificadas y el número de confirmaciones nuevas en cada una.


507
2017-07-15 17:32


origen


Respuestas:


Primer uso git remote update, para actualizar sus refs remotos. Luego puede hacer una de varias cosas, como:

  1. git status -uno le dirá si la rama que está rastreando está por delante, por detrás o ha divergido. Si no dice nada, lo local y lo remoto son lo mismo.

  2. git show-branch *master le mostrará los commits en todas las ramas cuyos nombres terminan en 'master' (ej. dominar y origen / maestro)

Si utiliza -v con git remote update (git remote -v update) puedes ver qué ramas se actualizaron, por lo que realmente no necesitas más comandos.

Sin embargo, parece que desea hacer esto en un script o programa y terminar con un valor verdadero / falso. Si es así, hay formas de verificar la relación entre su actual CABEZA commit y el responsable de la rama que está rastreando, aunque dado que hay cuatro resultados posibles, no puede reducirlo a una respuesta sí / no. Sin embargo, si estás preparado para hacer un pull --rebase entonces puede tratar "local está detrás" y "local ha divergido" como "necesidad de tirar", y los otros dos como "no es necesario tirar".

Puede obtener la identificación de confirmación de cualquier ref utilizando git rev-parse <ref>, entonces puedes hacer esto por dominar y origen / maestro y compararlos. Si son iguales, las ramas son iguales. Si no son iguales, quiere saber cuál está por delante del otro. Utilizando git merge-base master origin/master te dirá el ancestro común de ambas ramas, y si no han divergido, será lo mismo que una u otra. Si obtienes tres identificaciones diferentes, las ramas se han separado.

Para hacer esto correctamente, por ejemplo, en una secuencia de comandos, debe ser capaz de consultar la rama actual y la rama remota que está rastreando. La función bash-setting de bash en /etc/bash_completion.d tiene algún código útil para obtener nombres de sucursales. Sin embargo, es probable que en realidad no necesite obtener los nombres. Git tiene algunas buenas manos cortas para referirse a las ramas y confirmaciones (como se documenta en git rev-parse --help) En particular, puedes usar @ para la rama actual (suponiendo que no estás en un estado de cabeza separada) y @{u} para su rama ascendente (p. ej. origin/master) Asi que git merge-base @ @{u} devolverá la (hash of) la confirmación en la cual la rama actual y su upstream divergen y git rev-parse @ y git rev-parse @{u} te dará los hash de los dos consejos. Esto se puede resumir en el siguiente script:

#!/bin/sh

UPSTREAM=${1:-'@{u}'}
LOCAL=$(git rev-parse @)
REMOTE=$(git rev-parse "$UPSTREAM")
BASE=$(git merge-base @ "$UPSTREAM")

if [ $LOCAL = $REMOTE ]; then
    echo "Up-to-date"
elif [ $LOCAL = $BASE ]; then
    echo "Need to pull"
elif [ $REMOTE = $BASE ]; then
    echo "Need to push"
else
    echo "Diverged"
fi

Nota: versiones anteriores de git no permitieron @ por sí mismo, por lo que puede que tenga que usar @{0} en lugar.

La línea UPSTREAM=${1:-'@{u}'} le permite opcionalmente pasar una rama ascendente explícitamente, en caso de que quiera verificar contra una sucursal remota diferente a la configurada para la sucursal actual. Esto normalmente sería de la forma remotename / branchname. Si no se proporciona ningún parámetro, el valor predeterminado es @{u}.

El script asume que has hecho un git fetch o git remote update primero, actualizar las ramas de seguimiento. No incorporé esto en la secuencia de comandos porque es más flexible poder realizar la búsqueda y la comparación como operaciones separadas, por ejemplo, si quiere comparar sin buscar porque ya ha buscado recientemente.


683
2017-07-19 04:18



Si tienes una rama ascendente

git fetch <remote>
git status

Si no tienes una rama ascendente

Compara las dos ramas:

git fetch <remote>
git log <local_branch_name>..<remote_branch_name> --oneline

Por ejemplo:

git fetch origin

# See if there are any incoming changes
git log HEAD..origin/master --oneline

(Estoy asumiendo origin/master es su rama de seguimiento remoto)

Si se incluye alguna confirmación en el resultado anterior, entonces tiene cambios entrantes: debe fusionarse. Si no se enumeran las confirmaciones por git log entonces no hay nada que fusionar.

Tenga en cuenta que esto funcionará incluso si se encuentra en una rama de características, que no tiene un control remoto, ya que si se refiere explícitamente a origin/master en lugar de usar implícitamente rama aguas arriba recordado por Git.


115
2017-10-09 00:46



Si esto es para un script, puede usar:

git fetch
$(git rev-parse HEAD) == $(git rev-parse @{u})

(Nota: el beneficio de esta frente a las respuestas anteriores es que no necesita un comando por separado para obtener el nombre de la sucursal actual. "HEAD" y "@ {u}" (la rama actual de la sucursal) se ocupan de ello. "git rev-parse --help" para más detalles.)


46
2017-07-30 04:23



El comando

git ls-remote origin -h refs/heads/master

listará la cabecera actual del control remoto; puede compararla con un valor anterior o ver si tiene el SHA en su repositorio local.


33
2017-07-15 17:37



Aquí hay un delineador de Bash que compara el hash de confirmación HEAD de la sucursal actual contra su sucursal ascendente remota, no es pesado git fetch o git pull --dry-run operaciones requeridas:

[ $(git rev-parse HEAD) = $(git ls-remote $(git rev-parse --abbrev-ref @{u} | \
sed 's/\// /g') | cut -f1) ] && echo up to date || echo not up to date

Así es como esta línea algo densa se descompone:

  • Los comandos se agrupan y anidan usando $(x) Intento sustitución de comando sintaxis.
  • git rev-parse --abbrev-ref @{u} devuelve un ref upstream abreviado (p. origin/master), que luego se convierte en campos separados por espacios por el canal sed comando, p. origin master.
  • Esta cadena se alimenta en git ls-remote que devuelve la confirmación del encabezado de la rama remota. Este comando se comunicará con el repositorio remoto. El hilo cut comando extrae solo el primer campo (el hash de confirmación), eliminando la cadena de referencia separada por tabuladores.
  • git rev-parse HEAD devuelve el hash de confirmación local.
  • La sintaxis de Bash [ a = b ] && x || y completa el one-liner: esto es un Bash comparación de cuerdas  = dentro de una construcción de prueba [ test ], seguido de construcciones and-list y or-list && true || false.

25
2017-08-03 21:07



Te sugiero que veas el script https://github.com/badele/gitcheck. He codificado este script para verificar en un solo paso todos tus repositorios de Git, y muestra quién no se ha comprometido y quién no ha empujado / tirado.

Aquí un resultado de muestra:

Enter image description here


15
2018-04-27 12:08



Basé esta solución en los comentarios de @jberger.

if git checkout master &&
    git fetch origin master &&
    [ `git rev-list HEAD...origin/master --count` != 0 ] &&
    git merge origin/master
then
    echo 'Updated!'
else
    echo 'Not updated.'
fi

9
2018-06-19 13:10