Compruebe si es necesario tirar en Git

623

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

Ahora uso este simple script:

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 nuevas confirmaciones en cada una.

tomashin
fuente
14
Tenga en cuenta: "git pull --dry-run" no funciona como probablemente se esperaba. Parece que ese git pull pasa opciones desconocidas directamente a git fetch. El resultado es el de un tirón normal.
27
"extraer" es solo una forma corta de "buscar" y "fusionar" a la vez, si necesita verificar el estado del repositorio remoto, realmente está simulando una "búsqueda". Entonces git fetch -v --dry-runes lo que necesitas.
Claudio Floreani

Respuestas:

859

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

  1. git status -unole dirá si la rama que está rastreando está adelante, atrás o ha divergido. Si no dice nada, lo local y lo remoto son lo mismo.

  2. git show-branch *masterle mostrará las confirmaciones en todas las ramas cuyos nombres terminan en 'maestro' (por ejemplo, maestro y origen / maestro ).

Si usa -vcon git remote update( git remote -v update) puede ver qué ramas se actualizaron, por lo que realmente no necesita 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 compromiso HEAD actual y el jefe 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á preparado para hacer un pull --rebaseejercicio, entonces puede tratar "lo local está detrás" y "lo 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 referencia usando git rev-parse <ref>, por lo que puede hacer esto para master y origin / master y compararlos. Si son iguales, las ramas son iguales. Si son desiguales, desea saber cuál está por delante del otro. El uso git merge-base master origin/masterle dirá el antepasado común de ambas ramas, y si no han divergido, será lo mismo que una u otra. Si obtienes tres identificadores diferentes, las ramas se han separado.

Para hacerlo correctamente, por ejemplo, en un script, debe poder hacer referencia a la rama actual y a la rama remota que está rastreando. La función bash prompt-setting /etc/bash_completion.dtiene un código útil para obtener nombres de sucursales. Sin embargo, probablemente no necesite obtener los nombres. Git tiene algunas ordenadas shorthands para referirse a ramas y commits (como se documenta en git rev-parse --help). En particular, puede usarlo @para la rama actual (suponiendo que no esté en un estado de cabeza separada) y @{u}para su rama ascendente (por ejemplo origin/master). Por git merge-base @ @{u}lo tanto , devolverá el (hash del) commit en el que la rama actual y su flujo ascendente divergen git rev-parse @y git rev-parse @{u}le 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: las versiones anteriores de git no permitían @por sí mismas, por lo que es posible que deba usarlas @{0}.

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

La secuencia de comandos asume que has hecho uno git fetcho git remote updateprimero, para actualizar las ramas de seguimiento. No incluí esto en el script porque es más flexible poder realizar la recuperación y la comparación como operaciones separadas, por ejemplo, si desea comparar sin recuperar porque ya obtuvo recientemente.

Neil Mayhew
fuente
44
@takeshin Supongo que podría combinar git ls-remote origin -h refs / heads / master como lo sugiere @brool con git rev-list --max-count = 1 origin / master. Si devuelven el mismo hash, la rama remota no ha cambiado desde la última vez que actualizó sus referencias remotas (con extracción, recuperación, actualización remota, etc.) Esto tendría la ventaja de que no tendría que extraer el contenido de todos los commits de inmediato, pero podrían dejarlo para un momento más conveniente. Sin embargo, dado que la actualización remota no es destructiva, también podría hacerlo de todos modos.
Neil Mayhew
2
También podría intentarlo git status -s -u no, lo que da un resultado más corto que git status -u no.
Phillip Cloud
2
@mhulse, git remote -v update. Mira la salida de git remote --helppara una explicación más completa.
Neil Mayhew
1
@ChrisMaes Buen punto. Se necesita una sintaxis más explícita con versiones anteriores de git. Experimenté con los diversos sistemas que tengo y descubrí que @{u}funciona con git 1.8.3.2 pero @no funciona. Sin embargo @funciona con 1.8.5.4. Moraleja de la historia: git sigue mejorando y vale la pena tener la versión más reciente que puedas.
Neil Mayhew
1
Ahora se requiere un especificador para @. Puede usar @ {0} en lugar de @.
Ben Davis,
132

Si tienes una rama aguas arriba

git fetch <remote>
git status

Si no tienes una rama aguas arriba

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

(Supongo que origin/masteres su rama de seguimiento remoto)

Si hay confirmaciones enumeradas en el resultado anterior, entonces tiene cambios entrantes: debe fusionar. Si no se enumeran confirmaciones, git logentonces no hay nada que fusionar.

Tenga en cuenta que esto funcionará incluso si está en una rama de características, que no tiene un control remoto de seguimiento, ya que se refiere explícitamente en origin/masterlugar de usar implícitamente la rama ascendente recordada por Git.

Martillo de peste
fuente
2
Incluso git fetch; git log HEAD.. --onelinese puede usar una notación más corta si hay una rama remota predeterminada para la local.
phil pirozhkov
@philpirozhkov Si tiene una rama remota predeterminada, creo que debería hacer un simple "estado de git". Mi respuesta fue genérica para cualquiera de las dos ramas, donde una puede o no estar rastreando a la otra.
PlagueHammer
55
git rev-list HEAD...origin/master --countle dará el número total de confirmaciones "diferentes" entre los dos.
Jake Berger
1
Corto y simple. Mi solución favorita que solo muestra los nuevos commits (pulgares arriba dos veces)
spankmaster79
¿Cómo puedo usar esto en un archivo por lotes (Ubuntu), para poder ejecutar otros comandos solo en el caso de que este comando muestre que se necesita un pull?
Ulises Alves
69

Si esto es para un script, puede usar:

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

(Nota: el beneficio de esta respuesta frente a las respuestas anteriores es que no necesita un comando separado para obtener el nombre actual de la sucursal. "git rev-parse --help" para más detalles).

Stephen Haberman
fuente
Descubrí @ {u} de forma independiente y actualicé mi respuesta antes de ver la tuya.
Neil Mayhew
1
¿Mostrará git rev-parse @{u}realmente el último commit sin un git fetch?
Kyle Strand
3
Este fue el boleto! Sin ==embargo , su lógica está usando lo que significa "si NO hay cambios desde la parte superior". Solía !=buscar "si HAY cambios desde la parte superior" para mi aplicación. ¡No te olvides de git fetchprimero!
ChrisPrime
1
Agregué git fetch, porque realmente es necesario responder la pregunta original. @Es la abreviatura de HEADBTW.
user1338062
Los usuarios de Windows necesitarán comillas simples alrededor del @{u}por ejemplogit rev-parse '@{u}'
spuder
36

El comando

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

enumerará el encabezado actual en el control remoto; puede compararlo con un valor anterior o ver si tiene el SHA en su repositorio local.

brool
fuente
1
¿Algún script de muestra para comparar estos valores?
takeshin
18
git rev-list HEAD...origin/master --countle dará el número total de confirmaciones "diferentes" entre los dos.
Jake Berger
3
@jberger para aclarar, eso solo mostrará la cantidad de confirmaciones que está detrás (no adelante y atrás) y solo funciona si usted git fetcho el git remote updateprimero. git statusTambién muestra un recuento, por cierto.
Dennis
1
@Dennis pensé que ..es "commits en origen / master, restando HEAD" (es decir, número de commits detrás). Considerando que, ...es la diferencia simétrica (es decir, adelante y atrás)
Jake Berger
3
Excelente. Por lo que puedo decir, esta es la única solución que realmente comprueba el origen de las actualizaciones, pero no lo hace implícitamente fetch.
Kyle Strand
35

He aquí un golpe de una sola línea que compara CABEZA de la rama actual de hash cometen en contra de su rama ascendente a distancia, sin pesada git fetcho git pull --dry-runlas operaciones necesarias:

[ $(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 divide:

  • Los comandos se agrupan y anidan mediante la sintaxis de sustitución de comandos$(x) Bash .
  • git rev-parse --abbrev-ref @{u}devuelve una referencia ascendente abreviada (p origin/master. ej. ), que luego se convierte en campos separados por espacios mediante el sedcomando canalizado , p origin master. ej .
  • Esta cadena se alimenta en la git ls-remoteque devuelve el commit principal de la rama remota. Este comando se comunicará con el repositorio remoto. El cutcomando canalizado extrae solo el primer campo (el hash de confirmación), eliminando la cadena de referencia separada por tabulaciones.
  • git rev-parse HEAD devuelve el hash de confirmación local.
  • La sintaxis de Bash [ a = b ] && x || ycompleta la línea única: esta es una comparación de cadenas de Bash =dentro de una construcción de prueba [ test ], seguida de las construcciones de lista y lista && true || false.
wjordan
fuente
2
Yo no usar / g en la sed si utiliza barras en los nombres de las sucursales. Eso es "sed 's / \ // /" solamente.
Martyn Davis
@wjordan Su solución falla cuando no se puede acceder al repositorio remoto (o bajo mantenimiento) y se activará "actualizado"
marco
20

Te sugiero que veas el script https://github.com/badele/gitcheck . He codificado este script para verificar de una sola vez todos sus repositorios Git, y muestra quién no se ha comprometido y quién no ha empujado / retirado.

Aquí un resultado de muestra:

Ingrese la descripción de la imagen aquí

Bruno Adelé
fuente
66
ordenado, pensando en reescribirlo en pura concha
Olivier Refalo
1
Ahora, también puede usar gitcheck directamente desde un contenedor acoplable (con sus archivos en su host). Para obtener más información, consulte el proyecto gitcheck github
Bruno Adelé,
Una herramienta similar en bash git-multi-repo-tooling . git mrepo -cEsto mostrará todas las confirmaciones pendientes.
Greg
11

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
ma11hew28
fuente
refiriéndome a su comentario anterior , en este momento no puedo darle una respuesta definitiva. En el momento en que hice esos comentarios, me estaba sumergiendo en las profundidades de git y particularmente en los controles remotos y las diferencias. Han pasado unos meses desde entonces y gran parte de ese conocimiento está enterrado dentro de mi cerebro. ;) Si está buscando el número de confirmaciones 'diferentes' entre los dos, entonces ...parece ser una parte válida de su solución.
Jake Berger
1
Gracias. Esto estaba limpio
Shobhit Puri
10

Ya hay muchas respuestas ricas en funciones e ingeniosas. Para proporcionar un poco de contraste, podría conformarme con una línea muy simple.

# Check return value to see if there are incoming updates.
if ! git diff --quiet remotes/origin/HEAD; then
 # pull or whatever you want to do
fi
Thuovila
fuente
2
Faltaba la respuesta original '!' en el si. El valor de retorno de git diff es cero, cuando no hay cambios.
thuovila
La mejor solución de la OMI, aunque necesito sustituir "remotes / origin / HEAD" con "origin / master" u otra revisión
Matthias Michael Engh
9

Creo que la mejor manera de hacer esto sería:

git diff remotes/origin/HEAD

Suponiendo que tiene registrada esta especificación de referencia. Debería, si ha clonado el repositorio, de lo contrario (es decir, si el repositorio se creó localmente de novo y se envió al control remoto), debe agregar la especificación de referencia explícitamente.

Jeet
fuente
9

El siguiente script funciona perfectamente.

changed=0
git remote update && git status -uno | grep -q 'Your branch is behind' && changed=1
if [ $changed = 1 ]; then
    git pull
    echo "Updated successfully";
else
    echo "Up-to-date"
fi
Harikrishna
fuente
6

Haría el camino sugerido por brool. El siguiente script de una línea toma el SHA1 de su última versión confirmada y lo compara con el del origen remoto, y extrae los cambios solo si difieren. Y es aún más ligero de las soluciones basadas en git pullo git fetch.

[ `git log --pretty=%H ...refs/heads/master^` != `git ls-remote origin
-h refs/heads/master |cut -f1` ] && git pull
Claudio Floreani
fuente
Este comando falla si el repositorio de git se clona con "--depth 1" (para limitar el tamaño de descarga). ¿Sabes si hay una manera de arreglarlo?
Adam Ryczkowski
El registro git está devolviendo muchas líneas y dando un error "bash: [: demasiados argumentos" cambiaría agit rev-parse --verify HEAD
Drew Pierce
1
Esta es una comparación simple de cadenas realizada por bash. Si algo falla, le sugiero que verifique su sintaxis (es decir, está escribiendo mal) Primero ejecute git log --pretty=%H ...refs/heads/master^ para obtener el SHA1 de su última versión confirmada, y luego ejecute git ls-remote origin -h refs/heads/master |cut -f1 para obtener el SHA1 del origen remoto. Estos dos son comandos git y no tienen nada que ver con bash. Lo que hace bash dentro de los corchetes es comparar la salida del primer comando con el segundo, y si son iguales, devuelve verdadero y se ejecuta git pull.
Claudio Floreani
"y si son iguales, devuelve verdadero y se ejecuta git pull". Sé que estoy siendo quisquilloso, pero solo para salvar a alguien de la confusión, eso debería ser "y si no son iguales". Además, por cualquier razón, el primer comando git no funciona para mí. (Estoy en git 2.4.1.) Así que solo estoy usando en su git log --pretty=%H master | head -n1lugar. Pero no estoy seguro si eso es exactamente lo mismo.
xd1le
6

Si ejecuta este script, probará si la rama actual necesita un git pull:

#!/bin/bash

git fetch -v --dry-run 2>&1 |
    grep -qE "\[up\s+to\s+date\]\s+$(
        git branch 2>/dev/null |
           sed -n '/^\*/s/^\* //p' |
                sed -r 's:(\+|\*|\$):\\\1:g'
    )\s+" || {
        echo >&2 "Current branch need a 'git pull' before commit"
        exit 1
}

Es muy conveniente ponerlo como un compromiso previo de gancho Git para evitar

Merge branch 'foobar' of url:/path/to/git/foobar into foobar

cuando tu commitantespulling .

Para usar este código como un enlace, simplemente copie / pegue el script en

.git/hooks/pre-commit

y

chmod +x .git/hooks/pre-commit
Gilles Quenot
fuente
6

Solo quiero publicar esto como una publicación real, ya que es fácil pasarlo por alto en los comentarios.

La respuesta correcta y mejor para esta pregunta fue dada por @Jake Berger, muchas gracias amigo, todos necesitan esto y todos pierden esto en los comentarios. Entonces, para todos los que luchan con esto, esta es la respuesta correcta, solo use la salida de este comando para saber si necesita hacer un git pull. si la salida es 0, entonces obviamente no hay nada que actualizar.

@stackoverflow, dale unas campanas a este tipo. Gracias @ Jake Berger

git rev-list HEAD...origin/master --count will give you the total number of "different" commits between the two.  Jake Berger Feb 5 '13 at 19:23
diegeelvis_SA
fuente
4

Ejecute git fetch (remote)para actualizar sus referencias remotas, le mostrará las novedades. Luego, cuando finalice la compra de su sucursal local, le mostrará si está detrás del flujo ascendente.

che
fuente
Creo que ya ha verificado la sucursal local, por lo que necesita algo más para mostrar si está detrás, etc. Puede hacerlo con el estado de git.
Neil Mayhew
Es cierto, después de que haya obtenido controles remotos, también git statuslo mostrará.
che
1
Eso es algo de humor git pull --dry-run, pero creo que es demasiado pesado para que se ejecute un script cron cada minuto.
takeshin
@takeshin: no puede verificar repositorios remotos sin conectarse a la red. Si no hay nada nuevo fetch, no va a hacer mucho más que verificar el estado. Si necesita una reacción muy rápida y liviana en las actualizaciones remotas, es posible que desee considerar enganchar algún tipo de notificaciones al repositorio remoto.
che
@takeshin: si quieres comprobar el repositorio remoto cada minuto, creo que te has perdido el punto de DVCS. La idea es poder desarrollarse de forma independiente por un tiempo, y luego armar todo sin problemas más adelante. No es como cvs, svn, p4, etc., donde siempre tienes que estar trabajando además de lo que sea más reciente en el repositorio. Si realmente necesita algo en lo que alguien más está trabajando, entonces debe usar un mecanismo de comunicación diferente, como el correo electrónico, para decirle cuándo está listo para tirar.
Neil Mayhew
4

Todas esas sugerencias complejas mientras la solución es tan corta y fácil:

#!/bin/bash

BRANCH="<your branch name>"
LAST_UPDATE=`git show --no-notes --format=format:"%H" $BRANCH | head -n 1`
LAST_COMMIT=`git show --no-notes --format=format:"%H" origin/$BRANCH | head -n 1`

git remote update
if [ $LAST_COMMIT != $LAST_UPDATE ]; then
        echo "Updating your branch $BRANCH"
        git pull --no-edit
else
        echo "No updates available"
fi
Humano digital
fuente
LAST_COMMIT y LAST_UPDATE siempre son iguales incluso si hay cambios
canbax
Esta solución es buena y simple, debe git remote updateejecutarse antes de su código, para obtener la última información de confirmación de origen
ak93
¿ git remote updateNo debería agregarse antes de los git showcomandos?
Setop
2

Aquí está mi versión de un script Bash que verifica todos los repositorios en una carpeta predefinida:

https://gist.github.com/henryiii/5841984

Puede diferenciar entre situaciones comunes, como tirar necesario y empujar necesario, y es multiproceso, por lo que la búsqueda ocurre de una vez. Tiene varios comandos, como extracción y estado.

Coloque un enlace simbólico (o el script) en una carpeta en su ruta, luego funciona como git all status(, etc.). Solo admite origen / maestro, pero se puede editar o combinar con otro método.

Henry Schreiner
fuente
1
git ls-remote | cut -f1 | git cat-file --batch-check >&-

enumerará todo lo referenciado en cualquier control remoto que no esté en su repositorio. Tomar un poco los cambios de referencia remotos a cosas que ya tenía (por ejemplo, restablecimientos a confirmaciones anteriores) toma un poco más:

git pack-refs --all
mine=`mktemp`
sed '/^#/d;/^^/{G;s/.\(.*\)\n.* \(.*\)/\1 \2^{}/;};h' .git/packed-refs | sort -k2 >$mine
for r in `git remote`; do 
    echo Checking $r ...
    git ls-remote $r | sort -k2 | diff -b - $mine | grep ^\<
done
jthill
fuente
1

Tal vez esto, si desea agregar una tarea como crontab:

#!/bin/bash
dir="/path/to/root"
lock=/tmp/update.lock
msglog="/var/log/update.log"

log()
{
        echo "$(date) ${1:-missing}" >> $msglog
}

if [ -f $lock ]; then
        log "Already run, exiting..."
else
        > $lock
        git -C ~/$dir remote update &> /dev/null
        checkgit=`git -C ~/$dir status`
        if [[ ! "$checkgit" =~ "Your branch is up-to-date" ]]; then
                log "-------------- Update ---------------"
                git -C ~/$dir pull &>> $msglog
                log "-------------------------------------"
        fi
        rm $lock

fi
exit 0
Altzone
fuente
1

Usando regexp simple:

str=$(git status) 
if [[ $str =~ .*Your\ branch\ is\ behind.*by.*commits,\ and\ can\ be\ fast-forwarded ]]; then
    echo `date "+%Y-%m-%d %H:%M:%S"` "Needs pull"
else
    echo "Code is up to date"
fi
Tomas Kukis
fuente
Esto no funcionará. El estado de git es solo un control local, por lo que solo le indicaría si su sucursal está detrás si ya ha actualizado sus defs remotos.
minhaz1
0

Utilizo una versión de un script basada en la respuesta de Stephen Haberman:

if [ -n "$1" ]; then
    gitbin="git -C $1"
else
    gitbin="git"
fi

# Fetches from all the remotes, although --all can be replaced with origin
$gitbin fetch --all
if [ $($gitbin rev-parse HEAD) != $($gitbin rev-parse @{u}) ]; then
    $gitbin rebase @{u} --preserve-merges
fi

Suponiendo que se llama a este script git-fetch-and-rebase, se puede invocar con un argumento opcionaldirectory name del repositorio Git local para realizar la operación. Si se llama al script sin argumentos, se supone que el directorio actual es parte del repositorio de Git.

Ejemplos:

# Operates on /abc/def/my-git-repo-dir
git-fetch-and-rebase /abc/def/my-git-repo-dir

# Operates on the Git repository which the current working directory is part of
git-fetch-and-rebase

Está disponible aquí también.

Tuxdude
fuente
0

Después de leer muchas respuestas y múltiples publicaciones, y pasar medio día probando varias permutaciones, esto es lo que se me ocurrió.

Si está en Windows, puede ejecutar este script en Windows utilizando Git Bash proporcionado por Git para Windows (instalación o portátil).

Este script requiere argumentos

- ruta local, por ejemplo / d / source / project1
- URL de Git, por ejemplo, https: //[email protected]/username/project1.git
- contraseña

si no se debe ingresar una contraseña en la línea de comando en texto plano,
luego modifique el script para verificar si GITPASS está vacío; no haga
reemplazar y dejar que Git solicite una contraseña

El guión

- Find the current branch
- Get the SHA1 of the remote on that branch
- Get the SHA1 of the local on that branch
- Compare them.

Si hay un cambio tal como lo imprime el script, puede proceder a buscar o extraer. El script puede no ser eficiente, pero hace el trabajo por mí.

Actualización - 2015-10-30: stderr a dev nulo para evitar imprimir la URL con la contraseña en la consola.

#!/bin/bash

# Shell script to check if a Git pull is required.

LOCALPATH=$1
GITURL=$2
GITPASS=$3

cd $LOCALPATH
BRANCH="$(git rev-parse --abbrev-ref HEAD)"

echo
echo git url = $GITURL
echo branch = $BRANCH

# Bash replace - replace @ with :password@ in the GIT URL
GITURL2="${GITURL/@/:$GITPASS@}"
FOO="$(git ls-remote $GITURL2 -h $BRANCH 2> /dev/null)"
if [ "$?" != "0" ]; then
  echo cannot get remote status
  exit 2
fi
FOO_ARRAY=($FOO)
BAR=${FOO_ARRAY[0]}
echo [$BAR]

LOCALBAR="$(git rev-parse HEAD)"
echo [$LOCALBAR]
echo

if [ "$BAR" == "$LOCALBAR" ]; then
  #read -t10 -n1 -r -p 'Press any key in the next ten seconds...' key
  echo No changes
  exit 0
else
  #read -t10 -n1 -r -p 'Press any key in the next ten seconds...' key
  #echo pressed $key
  echo There are changes between local and remote repositories.
  exit 1
fi
Excepción en tiempo de ejecución
fuente
0

Para los usuarios de Windows que terminan en esta pregunta buscando esto, he modificado algunas de las respuestas en un script de PowerShell. Ajuste según sea necesario, guárdelo en un .ps1archivo y ejecútelo a pedido o programado si lo desea.

cd C:\<path to repo>
git remote update                           #update remote
$msg = git remote show origin               #capture status
$update = $msg -like '*local out of date*'
if($update.length -gt 0){                   #if local needs update
    Write-Host ('needs update')
    git pull
    git reset --hard origin/master
    Write-Host ('local updated')
} else {
    Write-Host ('no update needed')
}
Andrew Grothe
fuente
0

Debido a que la respuesta de Neils me ayudó mucho, aquí hay una traducción de Python sin dependencias:

import os
import logging
import subprocess

def check_for_updates(directory:str) -> None:
    """Check git repo state in respect to remote"""
    git_cmd = lambda cmd: subprocess.run(
        ["git"] + cmd,
        cwd=directory,
        stdout=subprocess.PIPE,
        check=True,
        universal_newlines=True).stdout.rstrip("\n")

    origin = git_cmd(["config", "--get", "remote.origin.url"])
    logging.debug("Git repo origin: %r", origin)
    for line in git_cmd(["fetch"]):
        logging.debug(line)
    local_sha = git_cmd(["rev-parse", "@"])
    remote_sha = git_cmd(["rev-parse", "@{u}"])
    base_sha = git_cmd(["merge-base", "@", "@{u}"])
    if local_sha == remote_sha:
        logging.info("Repo is up to date")
    elif local_sha == base_sha:
        logging.info("You need to pull")
    elif remote_sha == base_sha:
        logging.info("You need to push")
    else:
        logging.info("Diverged")

check_for_updates(os.path.dirname(__file__))

hth

Frans
fuente
-5

También puede encontrar un guión de Phing que hace eso ahora.

Necesitaba una solución para actualizar mis entornos de producción automáticamente y estamos muy contentos gracias a este script que estoy compartiendo.

El script está escrito en XML y necesita Phing .

Pol Dellaiera
fuente
Tal vez no sea una buena idea copiar y pegar el script aquí, todavía lo estoy actualizando ...
Pol Dellaiera