Question Vérifiez si la traction est nécessaire dans Git


Comment puis-je vérifier si le référentiel distant a changé et que je dois tirer?

Maintenant, j'utilise ce script simple:

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

Mais c'est plutôt lourd.

Y a-t-il un meilleur moyen? La solution idéale vérifie toutes les branches distantes et renvoie les noms des branches modifiées et le nombre de nouvelles validations dans chacune d'entre elles.


507
2017-07-15 17:32


origine


Réponses:


Première utilisation git remote update, pour mettre à jour vos références à distance. Ensuite, vous pouvez faire l'une des choses suivantes:

  1. git status -uno vous dira si la branche que vous suivez est en avance, en retard ou a divergé. S'il ne dit rien, le local et le distant sont les mêmes.

  2. git show-branch *master vous montrera les commits dans toutes les branches dont les noms se terminent en «maître» (par exemple maîtriser et origine / maître).

Si tu utilises -v avec git remote update (git remote -v update) vous pouvez voir quelles branches ont été mises à jour, vous n'avez donc pas besoin de commandes supplémentaires.

Cependant, il semble que vous souhaitiez le faire dans un script ou un programme et que vous obteniez une valeur true / false. Si oui, il existe des moyens de vérifier la relation entre votre courant TÊTE commit et le responsable de la branche que vous suivez, bien qu'il y ait quatre résultats possibles, vous ne pouvez pas le réduire à une réponse oui / non. Cependant, si vous êtes prêt à faire un pull --rebase alors vous pouvez traiter "local est derrière" et "local a divergé" comme "besoin de tirer", et les deux autres comme "n'ont pas besoin de tirer".

Vous pouvez obtenir l'ID de validation de toute référence en utilisant git rev-parse <ref>, donc vous pouvez le faire pour maîtriser et origine / maître et les comparer. Si elles sont égales, les branches sont les mêmes. S'ils sont inégaux, vous voulez savoir qui est en avance sur l'autre. En utilisant git merge-base master origin/master vous dira l'ancêtre commun des deux branches, et si elles n'ont pas divergé, ce sera le même que l'un ou l'autre. Si vous obtenez trois identifiants différents, les branches ont divergé.

Pour le faire correctement, par exemple dans un script, vous devez pouvoir vous référer à la branche actuelle et à la branche distante qu'elle suit. La fonction de réglage des invites bash dans /etc/bash_completion.d a un code utile pour obtenir les noms de branches. Cependant, vous n'avez probablement pas besoin d'obtenir les noms. Git a quelques raccourcis soignés pour se référer aux branches et commits (comme documenté dans git rev-parse --help). En particulier, vous pouvez utiliser @ pour la branche actuelle (en supposant que vous ne soyez pas dans un état détaché) et @{u} pour sa branche amont (par exemple origin/master). Alors git merge-base @ @{u} retournera le (hash de) la validation à laquelle la branche actuelle et son amont divergent et git rev-parse @ et git rev-parse @{u} vous donnera les hachages des deux conseils. Cela peut être résumé dans le script suivant:

#!/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

Remarque: les anciennes versions de git ne permettaient pas @ seul, vous devrez peut-être utiliser @{0} au lieu.

La ligne UPSTREAM=${1:-'@{u}'} vous permet en option de passer une branche amont explicitement, au cas où vous souhaiteriez vérifier une branche distante différente de celle configurée pour la branche en cours. Ce serait typiquement de la forme remotename / nom de la succursale. Si aucun paramètre n'est donné, la valeur par défaut est @{u}.

Le script suppose que vous avez fait un git fetch ou git remote update Premièrement, mettre à jour les branches de suivi. Je n'ai pas intégré cela dans le script, car il est plus flexible pour pouvoir effectuer la récupération et la comparaison en tant qu'opérations séparées, par exemple si vous voulez comparer sans récupérer car vous avez déjà été récupéré récemment.


683
2017-07-19 04:18



Si vous avez une branche en amont

git fetch <remote>
git status

Si vous n'avez pas de branche en amont

Comparez les deux branches:

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

Par exemple:

git fetch origin

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

(Je suppose origin/master est votre branche de suivi à distance)

Si des validations sont listées dans la sortie ci-dessus, alors vous avez des changements entrants - vous devez fusionner. Si aucun commit n'est répertorié par git log alors il n'y a rien à fusionner.

Notez que cela fonctionnera même si vous êtes sur une branche de fonctionnalité - qui n'a pas de suivi à distance, car si elle fait explicitement référence à origin/master au lieu d'utiliser implicitement le branche en amont rappelé par Git.


115
2017-10-09 00:46



Si c'est pour un script, vous pouvez utiliser:

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

(Note: l'avantage de cette réponse par rapport aux réponses précédentes est que vous n'avez pas besoin d'une commande séparée pour obtenir le nom de la branche actuelle. "HEAD" et "@ {u}" (l'amont de la branche actuelle) s'en occupe. "git rev-parse --help" pour plus de détails.)


46
2017-07-30 04:23



La commande

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

listera la tête actuelle sur la télécommande - vous pouvez le comparer à une valeur précédente ou voir si vous avez le SHA dans votre repo local.


33
2017-07-15 17:37



Voici un Bash one-liner qui compare le hachage de commit HEAD de la branche actuelle à sa branche distante en amont, sans lourd git fetch ou git pull --dry-run opérations requises:

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

Voici comment cette ligne un peu dense est décomposée:

  • Les commandes sont groupées et imbriquées en utilisant $(x) Frapper commande-substitution syntaxe.
  • git rev-parse --abbrev-ref @{u} renvoie une référence amont abrégée (par ex. origin/master), qui est ensuite converti en champs séparés par des espaces sed commande, par ex. origin master.
  • Cette chaîne est alimentée dans git ls-remote qui renvoie la tête de validation de la branche distante. Cette commande communiquera avec le référentiel distant. Le tuyau cut commande extrait uniquement le premier champ (le hachage de validation), en supprimant la chaîne de référence séparée par des tabulations.
  • git rev-parse HEAD renvoie le hachage de validation local.
  • La syntaxe Bash [ a = b ] && x || y complète le one-liner: c'est un Bash comparaison de chaînes  = dans une construction de test [ test ], suivi par les constructions and-list et /-list && true || false.

25
2017-08-03 21:07



Je vous suggère d'aller voir le script https://github.com/badele/gitcheck. J'ai codé ce script pour vérifier en un passage tous vos dépôts Git, et il montre qui n'a pas commis et qui n'a pas poussé / tiré.

Voici un exemple de résultat:

Enter image description here


15
2018-04-27 12:08



J'ai basé cette solution sur les commentaires 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



Je pense que la meilleure façon de le faire serait:

git diff remotes/origin/HEAD

En supposant que vous avez enregistré ce refspec. Vous devriez si vous avez cloné le référentiel, sinon (si le repo a été créé de novo localement, et poussé vers la télécommande), vous devez ajouter explicitement la refspec.


8
2017-07-16 01:18



Il existe déjà de nombreuses réponses très riches et ingénieuses. Pour fournir un peu de contraste, je pourrais me contenter d'une ligne très 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

8
2017-10-06 08:32



Je ferais le chemin suggéré par BROOL. Le script d'une ligne suivant prend le SHA1 de votre dernière version validée et le compare à celui de l'origine distante, et ne tire les modifications que si elles diffèrent. Et c'est encore plus léger des solutions basées sur git pull ou git fetch.

[ `git log --pretty=%H ...refs/heads/master^` != `git ls-remote origin
-h refs/heads/master |cut -f1` ] && git pull

6
2018-03-10 17:42