Verifique se é necessário puxar no Git

623

Como verifico se o repositório remoto foi alterado e preciso extrair?

Agora eu uso este script simples:

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

Mas é bastante pesado.

Existe uma maneira melhor? A solução ideal verificaria todas as ramificações remotas e retornaria os nomes das ramificações alteradas e o número de novas confirmações em cada uma.

leva
fonte
14
Observe: "git pull --dry-run" não funciona como o esperado. Parece que o git pull passa opções desconhecidas diretamente para o git fetch. O resultado é o de um pull normal do git.
27
"pull" é apenas uma maneira curta de "buscar" e "mesclar" de uma só vez, se você precisar verificar o status de repo remoto, realmente está simulando uma "busca". Então git fetch -v --dry-runé o que você precisa.
Claudio Floreani

Respostas:

859

Primeiro uso git remote update, para atualizar seus árbitros remotos. Então você pode fazer uma de várias coisas, como:

  1. git status -unodirá se o ramo que você está rastreando está à frente, atrás ou divergiu. Se não diz nada, o local e o remoto são os mesmos.

  2. git show-branch *mastermostrará os commits em todos os ramos cujos nomes terminam em 'master' (por exemplo, master e origin / master ).

Se você usar -vcom git remote update( git remote -v update), poderá ver quais ramificações foram atualizadas, para que você realmente não precise de mais comandos.

No entanto, parece que você deseja fazer isso em um script ou programa e acabar com um valor verdadeiro / falso. Nesse caso, existem maneiras de verificar o relacionamento entre o commit HEAD atual e o chefe do ramo que você está rastreando, embora como haja quatro resultados possíveis, você não possa reduzi-lo a uma resposta sim / não. No entanto, se você estiver preparado para fazer um pull --rebaseprocedimento, poderá tratar "o local está atrasado" e "o local está diferente" como "precisa puxar", e os outros dois como "não precisam puxar".

Você pode obter o ID de confirmação de qualquer ref usando git rev-parse <ref>, para fazer isso para mestre e origem / mestre e compará-los. Se são iguais, os galhos são os mesmos. Se eles são desiguais, você quer saber o que está à frente do outro. Usar git merge-base master origin/masterindica o ancestral comum de ambos os ramos, e se eles não divergiram, será o mesmo que um ou outro. Se você obtiver três IDs diferentes, os ramos divergirão.

Para fazer isso corretamente, por exemplo, em um script, você deve poder se referir à ramificação atual e à ramificação remota que está rastreando. A função de configuração do prompt do bash /etc/bash_completion.dpossui algum código útil para obter nomes de ramificações. No entanto, você provavelmente não precisa obter os nomes. O Git possui algumas regras simples para se referir a ramificações e confirmações (conforme documentado em git rev-parse --help). Em particular, você pode usar @a ramificação atual (supondo que você não esteja em um estado de cabeça desanexada) e @{u}a ramificação upstream (por exemplo origin/master). Assim, git merge-base @ @{u}irá retornar o (hash do) cometer pelo qual o ramo atual e seu divergem montante e git rev-parse @e git rev-parse @{u}lhe dará os hashes das duas pontas. Isso pode ser resumido no seguinte 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: as versões mais antigas do git não eram permitidas @por si só, então você pode ter que usá-lo @{0}.

A linha UPSTREAM=${1:-'@{u}'}permite que você passe opcionalmente uma ramificação upstream explicitamente, caso deseje verificar uma ramificação remota diferente daquela configurada para a ramificação atual. Isso normalmente seria no formato remotename / branchname . Se nenhum parâmetro for fornecido, o valor será padronizado como @{u}.

O script pressupõe que você tenha feito um git fetchou git remote updateprimeiro, para atualizar as ramificações de rastreamento. Não criei isso no script porque é mais flexível poder fazer a busca e a comparação como operações separadas, por exemplo, se você deseja comparar sem buscar porque já buscou recentemente.

Neil Mayhew
fonte
4
@takeshin Eu acho que você pode combinar a origem remota git ls-h refs / heads / master conforme sugerido por @brool com a lista rev git --max-count = 1 origin / master. Se eles retornarem o mesmo hash, a ramificação remota não será alterada desde a última atualização de suas referências remotas (com pull, busca, atualização remota etc.). Isso teria a vantagem de que você não precisaria baixar o conteúdo de todos os commits imediatamente, mas poderiam deixar isso para um momento mais conveniente. No entanto, como a atualização remota não é destrutiva, você também pode fazê-lo.
Neil Mayhew
2
Você também pode tentar git status -s -u no, o que fornece uma saída menor que git status -u no.
Phillip Cloud
2
@mhulse git remote -v update,. Veja a saída de git remote --helppara uma explicação mais completa.
Neil Mayhew
1
@ChrisMaes Bom ponto. A sintaxe mais explícita é necessária nas versões mais antigas do git. Eu experimentei os vários sistemas que tenho e descobri que @{u}funciona com o git 1.8.3.2, mas @não funciona. No entanto, @funciona com 1.8.5.4. Moral da história: o git continua melhorando e vale a pena ter a versão mais recente possível.
Neil Mayhew
1
Um especificador agora é necessário para @. Você pode usar @ {0} em vez de @.
Ben Davis
132

Se você tem um ramo upstream

git fetch <remote>
git status

Se você não tem um ramo upstream

Compare os dois ramos:

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

Por exemplo:

git fetch origin

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

(Presumo que origin/masterseja seu ramo de rastreamento remoto)

Se algum commit estiver listado na saída acima, você terá as alterações recebidas - você precisará mesclar. Se nenhum commit estiver listado até git loglá, não há nada para mesclar.

Observe que isso funcionará mesmo se você estiver em um ramo de recurso - que não possui um controle remoto de rastreamento, pois se refere explicitamente ao origin/masterinvés de usar implicitamente o ramo upstream lembrado pelo Git.

PlagueHammer
fonte
2
Mesmo uma notação mais curta git fetch; git log HEAD.. --onelinepode ser usada se houver uma ramificação remota padrão para a local.
phil Pirozhkov
@philpirozhkov Se você tem uma ramificação remota padrão, acho que um simples "status git". Minha resposta foi genérica para dois ramos, onde um pode ou não estar rastreando o outro.
PlagueHammer
55
git rev-list HEAD...origin/master --countfornecerá o número total de confirmações "diferentes" entre as duas.
Jake Berger
1
curto e simples. Minha solução favorita, que mostra apenas os novos commit (polegar para cima duas vezes)
spankmaster79
Como posso usar isso em um arquivo em lotes (Ubuntu), para que eu possa executar outros comandos apenas no caso de esse comando mostrar que é necessária uma solicitação?
Ulysses Alves
69

Se for para um script, você pode usar:

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

(Observação: o benefício dessas respostas vs. respostas anteriores é que você não precisa de um comando separado para obter o nome da filial atual. "HEAD" e "@ {u}" (upstream da filial atual) cuidam disso. "git rev-parse --help" para mais detalhes.)

Stephen Haberman
fonte
Eu descobri @ {u} de forma independente e atualizei minha resposta antes de ver a sua.
Neil Mayhew
1
Vai git rev-parse @{u}realmente mostrar o mais recente comprometer sem um git fetch?
Kyle Strand
3
Este foi o bilhete! Embora, sua lógica esteja sendo usada, o ==que significa "se NÃO houver alterações no upstream". Eu costumava !=verificar "se há alterações do upstream" para o meu aplicativo. Não se esqueça de git fetchprimeiro!
ChrisPrime
1
Eu adicionei o git fetch, porque é realmente necessário responder à pergunta original. @é curto para HEADbtw.
user1338062
Os usuários do Windows terão aspas simples em torno do @{u}exgit rev-parse '@{u}'
spuder
36

O comando

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

listará o cabeçalho atual no controle remoto - você pode compará-lo com um valor anterior ou verificar se possui o SHA no seu repositório local.

brool
fonte
1
Algum script de amostra para comparar esses valores?
takeshin
18
git rev-list HEAD...origin/master --countfornecerá o número total de confirmações "diferentes" entre as duas.
Jake Berger
3
@ jberger para esclarecer, isso mostrará apenas o número de confirmações que você está atrasando (não adiantando e atrasando) e só funciona se você git fetchou a git remote updateprimeira. git statustambém mostra uma contagem, btw.
Dennis
1
@ Dennis eu pensei que ..é "confirma na origem / mestre, subtraindo HEAD" (ou seja, número de confirmações atrasadas). Considerando que, ...é a diferença simétrica (ie frente e para trás)
Jake Berger
3
Excelente. Até onde eu sei, esta é a única solução que realmente verifica a origem em busca de atualizações, mas não faz implicitamente a fetch.
Kyle Strand
35

Aqui está uma Bash one-liner que compara HEAD do ramo atual comprometer de hash contra a sua filial a montante remoto, não pesada git fetchou git pull --dry-runoperações exigidas:

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

Veja como essa linha um tanto densa é dividida:

  • Os comandos são agrupados e aninhados usando a substituição de comandos do$(x) Bash sintaxe de .
  • git rev-parse --abbrev-ref @{u}retorna um ref upstream abreviado (por exemplo origin/master), que é então convertido em campos separados por espaço pelo sedcomando canalizado , por exemploorigin master .
  • Essa cadeia é inserida na git ls-remotequal retorna a confirmação principal da ramificação remota. Este comando se comunicará com o repositório remoto. O canalizadocut comando extrai apenas o primeiro campo (o hash de confirmação), removendo a cadeia de referência separada por tabulação.
  • git rev-parse HEAD retorna o hash de confirmação local.
  • A sintaxe do Bash [ a = b ] && x || yconclui a linha única: esta é uma comparação de string do Bash =em uma construção de teste [ test ], seguida pelas construções and-list e ou list && true || false.
wjordan
fonte
2
Eu não usaria / g no sed se você usar barras nos nomes dos ramos. Isso é apenas "sed '/ \ // /".
Martyn Davis
@wjordan Sua solução falha quando o repositório remoto não está acessível (ou sob manutenção) e irá desencadear "até à data"
quadro
20

Eu sugiro que você vá ver o script https://github.com/badele/gitcheck . Eu codifiquei esse script para fazer check-in em uma passagem em todos os seus repositórios Git e mostra quem não fez o commit e quem não fez push / pull.

Aqui está um exemplo de resultado:

Digite a descrição da imagem aqui

Bruno Adelé
fonte
6
puro, pensamento sobre reescrevê-lo com casca pura
Olivier Refalo
1
Agora, você também pode usar gitcheck diretamente de um recipiente janela de encaixe (com seus arquivos em seu host) Para mais informações consulte o projeto gitcheck github
de Bruno Adele
Uma ferramenta semelhante no bash git-multi-repo-tooling . git mrepo -cisso exibirá todas as confirmações pendentes.
1874 Greg Greg
11

Baseei esta solução nos comentários do @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
fonte
referindo-se ao seu comentário anterior , neste momento não posso dar uma resposta definitiva. Na época em que fiz esses comentários, eu estava mergulhando nas profundezas do git e, particularmente, controles remotos e diferenças. Faz alguns meses desde então e muito desse conhecimento está enterrado dentro do meu cérebro. ;) Se você está procurando o número de confirmações 'diferentes' entre as duas, ...parece ser uma parte válida da sua solução.
Jake Berger
1
Obrigado. Isso estava limpo.
Shobhit Puri
10

Já existem muitas respostas muito ricas e engenhosas. Para fornecer algum contraste, eu poderia me contentar com uma linha muito simples.

# 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
fonte
2
Faltava a resposta original '!' no se. O valor de retorno do git diff é zero, quando não há alterações.
thuovila
A melhor solução da IMO por aí, embora eu precise substituir "remotes / origin / HEAD" por "origin / master" ou outra revisão
Matthias Michael Engh
9

Eu acho que a melhor maneira de fazer isso seria:

git diff remotes/origin/HEAD

Supondo que você tenha este refspec registrado. Se você clonou o repositório, caso contrário (ou seja, se o repositório foi criado de novo localmente e enviado para o controle remoto), é necessário adicionar o refspec explicitamente.

Jeet
fonte
9

O script abaixo funciona perfeitamente.

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
fonte
6

Eu faria o caminho sugerido pelo brool. O script de uma linha a seguir pega o SHA1 da sua última versão confirmada e o compara com o da origem remota e extrai as alterações somente se elas diferirem. E é ainda mais leve das soluções baseadas em git pullou git fetch.

[ `git log --pretty=%H ...refs/heads/master^` != `git ls-remote origin
-h refs/heads/master |cut -f1` ] && git pull
Claudio Floreani
fonte
Este comando falha, se o repositório git for clonado com "- profundidade 1" (para limitar o tamanho do download). Você sabe, se existe uma maneira de corrigi-lo?
Adam Ryczkowski
O log do git está retornando muitas linhas e dando um erro "bash: [: muitos argumentos" que eu trocaria paragit rev-parse --verify HEAD
Drew Pierce
1
Esta é uma comparação simples de strings feita pelo bash. Se algo falhar, sugiro que verifique sua sintaxe (ou seja, você está digitando errado). Primeiro, execute git log --pretty=%H ...refs/heads/master^ o SHA1 da sua última versão confirmada e, em seguida, execute git ls-remote origin -h refs/heads/master |cut -f1 o SHA1 da origem remota. Esses dois são comandos git e não têm nada a ver com o bash. O que o bash faz dentro dos colchetes é comparar a saída do primeiro comando com o segundo e, se forem iguais, retornará true e será executado git pull.
Claudio Floreani
"e se forem iguais, retorna verdadeiro e roda git pull". Eu sei que estou sendo meticuloso, mas apenas para salvar a confusão de alguém, isso deve ser "e se não for igual". Além disso, por qualquer motivo, o primeiro comando git não funciona para mim. (Estou no git 2.4.1.) Então, estou apenas usando git log --pretty=%H master | head -n1. Mas não tenho certeza se é exatamente o mesmo.
Xd1le
6

Se você executar esse script, ele testará se a ramificação atual precisa de 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
}

É muito conveniente colocá-lo como um pré-commit de gancho do Git para evitar

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

quando você commitantespulling .

Para usar esse código como um gancho, basta copiar / colar o script em

.git/hooks/pre-commit

e

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

Eu só quero postar isso como um post real, pois é fácil perder isso nos comentários.

A resposta correta e melhor para esta pergunta foi dada por @Jake Berger, Muito obrigado cara, todo mundo precisa disso e todo mundo sente falta disso nos comentários. Portanto, para todos que lutam com isso aqui é a resposta correta, basta usar a saída deste comando para saber se você precisa executar um git pull. se a saída for 0, obviamente não há nada a atualizar.

@stackoverflow, dê a esse cara um sinal. Obrigado @ 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
fonte
4

Execute git fetch (remote)para atualizar suas referências remotas; ele mostrará as novidades. Então, quando você fizer o checkout de sua filial local, ele mostrará se está atrasado.

che
fonte
Eu acho que ele já tem a filial local, então ele precisa de outra coisa para mostrar se está atrasado etc. Ele pode fazer isso com o status git.
Neil Mayhew
É verdade que depois de buscar os controles remotos, git statusisso também será mostrado.
che
1
Isso é algo de bom humor git pull --dry-run, mas acho que é muito pesado para um script cron ser executado a cada minuto.
takeshin
@ takeshin: Você não pode verificar repositórios remotos sem acessar a rede. Se não houver algo novo fetch, não haverá muito mais do que verificar o status. Se você precisar de uma reação muito rápida e leve em atualizações remotas, convém conectar algum tipo de notificação ao repositório remoto.
che
@ takeshin: se você quiser verificar o repo remoto a cada minuto, acho que perdeu o objetivo do DVCS. A idéia toda é ser capaz de se desenvolver de forma independente por um tempo e, depois, reunir tudo isso sem problemas. Não é como cvs, svn, p4 etc. onde você sempre precisa trabalhar em cima do que for mais recente no repositório. Se você realmente precisa de algo em que outra pessoa esteja trabalhando, use um mecanismo de comunicação diferente, como e-mail, para informar quando está pronto para receber.
Neil Mayhew
4

Todas essas sugestões complexas, enquanto a solução é tão curta e 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
Digital Human
fonte
LAST_COMMIT e LAST_UPDATE são sempre iguais, mesmo se houver alterações
canbax
Esta solução é boa e simples, colocar as necessidades ter git remote updateexecutado antes de seu código, para receber as últimas origem comprometer informações
ak93
git remote updateNão deve acrescentar antes dos git showcomandos?
Setop
2

Aqui está minha versão de um script Bash que verifica todos os repositórios em uma pasta predefinida:

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

Ele pode diferenciar situações comuns, como puxar necessário e empurrar necessário, e é multithread, para que a busca ocorra ao mesmo tempo. Possui vários comandos, como pull e status.

Coloque um link simbólico (ou o script) em uma pasta no seu caminho e funcione como git all status(, etc.). Ele suporta apenas origem / mestre, mas pode ser editado ou combinado com outro método.

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

listará tudo o que for mencionado em qualquer controle remoto que não esteja no seu repositório. Para capturar alterações remotas de ref nas coisas que você já tinha (por exemplo, redefine para confirmações anteriores), é necessário um pouco mais:

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
fonte
1

Talvez isso, se você deseja adicionar uma tarefa 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
fonte
1

Usando regexp simples:

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
fonte
Isso não vai funcionar. O status git é apenas uma verificação local e, portanto, apenas informa se o seu ramo está atrasado se você já atualizou seus defs remotos.
Minhaz1 16/03/19
0

Eu uso uma versão de um script com base na resposta 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

Supondo que esse script seja chamado git-fetch-and-rebase, ele pode ser chamado com um argumento opcionaldirectory name do repositório Git local para executar a operação. Se o script for chamado sem argumentos, ele assumirá que o diretório atual faça parte do repositório Git.

Exemplos:

# 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á disponível aqui também.

Tuxdude
fonte
0

Depois de ler muitas respostas e várias postagens, e passar meio dia tentando várias permutações, é isso que eu criei.

Se você estiver no Windows, poderá executar este script no Windows usando o Git Bash fornecido pelo Git for Windows (instalação ou portátil).

Este script requer argumentos

- caminho local, por exemplo, / d / source / project1
- URL do Git, por exemplo, https: //[email protected]/username/project1.git
- senha

se uma senha não deve ser inserida na linha de comando em texto sem formatação,
modifique o script para verificar se GITPASS está vazio; não
substitua e deixe o Git solicitar uma senha

O script irá

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

Se houver uma alteração impressa pelo script, você poderá buscar ou puxar. O script pode não ser eficiente, mas faz o trabalho por mim.

Atualização - 30/10/2015: stderr to dev null para impedir a impressão do URL com a senha no console.

#!/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
Exceção de tempo de execução
fonte
0

Para os usuários do Windows que acabam com essa pergunta procurando, modifiquei algumas das respostas em um script do PowerShell. Ajuste conforme necessário, salve em um .ps1arquivo e execute sob demanda ou agendado, se desejar.

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
fonte
0

Como a resposta de Neils me ajudou muito, aqui está uma tradução em Python sem dependências:

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
fonte
-5

Você também pode encontrar um script Phing que faz isso agora.

Eu precisava de uma solução para atualizar meus ambientes de produção automaticamente e estamos muito felizes graças a este script que estou compartilhando.

O script é escrito em XML e precisa de Phing .

Pol Dellaiera
fonte
Talvez não seja uma boa idéia para copiar e colar o script aqui, eu ainda estou atualizando-o ...
Pol Dellaiera