git: savoir par programme combien la twig est en avance / derrière une twig distante

Je voudrais extraire les informations imprimées après un git status , qui ressemble à:

 # On branch master # Your branch is ahead of 'origin/master' by 2 commits. 

Bien sûr, je peux parsingr la sortie du git status mais ceci n’est pas recommandé car cette sortie lisible par l’homme est susceptible de changer.

Il y a deux problèmes:

  1. Comment connaître la twig distante suivie? Il est souvent d’ origin/branch mais pas nécessairement.
  2. Comment obtenir les chiffres? Comment savoir si elle est en avance / en retard? De combien de commits? Et qu’en est-il de la twig divergente?

mettre à jour

Comme indiqué par Amalloy, les versions récentes de git prennent en charge la recherche de la twig de suivi correspondante pour une twig donnée en indiquant “branchname @ {upstream}” (ou “branchname @ {u}” ou “@ {u}” pour la twig de suivi) de HEAD). Cela remplace efficacement le script ci-dessous. Tu peux faire:

 git rev-list @{u}.. git rev-list --left-right --boundary @{u}... gitk @{u}... 

etc. Par exemple, j’ai git q aliasing pour git log --pretty='...' @{u}.. pour me montrer les commits en attente prêts à être lancés.

réponse originale

Il ne semble pas y avoir de moyen facile de trouver la twig de suivi en général, sans parsingr beaucoup plus de configuration de git que ce qui est pratique dans quelques commandes de shell. Mais dans de nombreux cas, cela ira loin:

 # 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 

Une autre approche plus brute:

 git rev-list HEAD --not --remotes 

La réponse de jamessan explique comment trouver les différences relatives entre $ tracking_branch et HEAD en utilisant git rev-list . Une chose amusante que vous pouvez faire:

 git rev-list --left-right $tracking_branch...HEAD 

(notez trois points entre $ tracking_branch et HEAD). Cela montrera les commits sur les deux “arm” avec un signe distinctif à l’avant: “<" pour les commits sur $ tracking_branch et ">” pour les commits sur HEAD.

git rev-list origin..HEAD affichera les commits qui se trouvent dans votre twig actuelle, mais pas l’origine – c’est-à-dire si vous êtes en avance sur l’origine et par quels commits.

git rev-list HEAD..origin montrera le contraire.

Si les deux commandes montrent des commits, vous avez des twigs divergentes.

Vous pouvez essayer git branch -v -v . Avec l’ -v deux resockets, il affiche les noms des twigs en amont. Sortie de l’échantillon:

 * devel 7a5ff2c [origin/devel: ahead 1] smaller file status overlay icons master 37ca389 [origin/master] initial project check-in. 

Je pense que ce format est plus stable que la sortie d’ git status .

Edit: Ma réponse originale n’était en fait pas très bonne car elle comptait sur l’utilisateur d’avoir une télécommande appelée “origine”. Il a également échoué si la twig actuelle avait une twig de suivi en dehors de la source. Ces défauts l’ont essentiellement rendu inutile. Cependant, la réponse de @araqnid n’est pas la méthode la plus efficace et la façon dont il parvient à $tracking_branch est loin d’être évidente. La méthode la plus efficace (la plus rapide) que j’ai trouvée pour obtenir les mêmes fonctionnalités est la suivante:

 # 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 # inspired by @adam_spiers set -- $(git rev-list --left-right --count $tracking_branch...HEAD) behind=$1 ahead=$2 

réponse originale: (inférieure, mais donnée pour plus de clarté)

Peut-être la méthode la plus simple que j’ai pu trouver (inspirée par @insidepower)

 # count the number of logs behind=$(git log --oneline HEAD..origin | wc -l) ahead=$( git log --oneline origin..HEAD | wc -l) 

J’avais auparavant utilisé la méthode de @araqnid, mais maintenant je pense que je vais déplacer certains de mes scripts vers cette méthode car c’est beaucoup plus simple. Cela devrait fonctionner sur n’importe quel système Unix.

git status a une option --porcelain destinée à être analysée par des scripts. Il est basé sur la sortie --short – ils sont presque identiques au moment de l’écriture (voir la section “Porcelain Format” de la page de manuel git status pour plus de détails). La principale différence est que --short a une sortie couleur.

Par défaut, aucune information de twig n’est affichée, mais si vous ajoutez l’option --branch , vous obtiendrez une sortie comme:

 git status --short --branch ## master...origin/master [ahead 1] ?? untrackedfile.txt ... 

Si vous êtes à jour (après une extraction), la ligne sera simplement:

 ## master 

Si vous êtes en avance:

 ## master...origin/master [ahead 1] 

Si vous êtes en retard:

 ## master...origin/master [behind 58] 

Et pour les deux:

 ## master...origin/master [ahead 1, behind 58] 

Notez que git status --porcelain --branch n’est disponible que dans 1.7.10.3 ou ultérieur (bien que git status --short --branch soit disponible depuis 1.7.2 ).

Dans les versions modernes de git, @{u} pointe vers l’amont de la twig actuelle, s’il en existe une.

Donc, pour compter combien de commits vous êtes derrière la twig de suivi à distance:

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

Et pour voir jusqu’où vous êtes en avance sur la télécommande, changez simplement l’ordre:

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

Pour un résumé plus lisible, vous pouvez demander un journal à la place:

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

Pour mes propres besoins, je travaille sur un script qui remplacera @{u} par une supposition appropriée, si aucun stream amont n’est encore défini. Malheureusement, il n’y a actuellement pas de @{d} pour représenter l’aval (où vous allez pousser).

Pourquoi cela ne fonctionnerait pas:

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

La partie supérieure du code dans la réponse de araqnid ne fonctionne pas pour moi, alors peut-être que quelque chose dans git a changé depuis sa rédaction il y a 18 mois. Cela fonctionne si je change:

 tracking_branch=refs/remotes/$remote/$remote_branch 

à

 tracking_branch=$remote/$remote_branch 

Cependant, il existe toujours un problème lors du suivi d’une twig locale, auquel cas vous devez découper la partie distante (qui devient «.»):

 tracking_branch=${tracking_branch#./} 

Vous pouvez ensuite obtenir par programme le nombre de révisions suivantes et à venir:

 set -- `git rev-list --left-right --count $tracking_branch...HEAD` behind="$1" ahead="$2" 

J’ai écrit des scripts pour faire tout ça (et plus encore – par exemple, ils peuvent aussi essayer de repérer des télécommandes de l’autre côté d’un pont git-svn) et les publier dans mon repository git-config sur github . Par exemple, voici mon git-compare-upstream . Consultez le fichier README pour obtenir des instructions d’installation et d’autres scripts utiles.

Comment connaître la twig distante suivie? Il est souvent d’ origin/branch mais pas nécessairement.

Git 2.5+ introduit un nouveau raccourci qui fait référence à la twig vers laquelle vous poussez. @{push} : ce serait la twig de suivi à distance qui est intéressante ici.

Cela signifie que vous avez une autre option pour voir en avant / en arrière pour toutes les twigs configurées pour pousser vers une twig.

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

Voir plus à la section ” Affichage de Git Commits non compressés ”