Journal Git pour obtenir des validations uniquement pour une branche spécifique


214

Je veux lister tous les commits qui ne sont qu'une partie d'une branche spécifique.

Avec ce qui suit, il répertorie toutes les validations de la branche, mais aussi du parent (maître)

git log mybranch

L'autre option que j'ai trouvée, était d'exclure les commits accessibles par le maître et me donne ce que je veux, MAIS je voudrais éviter d'avoir à connaître les noms des autres branches.

git log mybranch --not master

J'essayais d'utiliser git for-each-ref, mais il répertorie également mybranch donc il exclut en fait tout:

git log mybranch --not $(git for-each-ref --format '^%(refname:short)' refs/heads/)

Mettre à jour:

Je teste une nouvelle option que j'ai trouvée il y a quelque temps, et jusqu'à présent, il semble que cela pourrait être ce que je cherchais:

git log --walk-reflogs mybranch

Mise à jour (2013-02-13T15: 08):

L'option --walk-reflogs est bonne, mais j'ai vérifié qu'il y a une expiration pour reflogs (90 jours par défaut, gc.reflogExpire ).

Je pense avoir trouvé la réponse que je cherchais:

git log mybranch --not $(git for-each-ref --format='%(refname)' refs/heads/ | grep -v "refs/heads/mybranch")

Je supprime simplement la branche actuelle de la liste des branches disponibles et j'utilise cette liste pour être exclue du journal. De cette façon, je ne reçois que les commits qui ne sont atteints que par mybranch .



Déjà vu cette question aussi, mais pas la même
dimirc

2
Etes-vous sûr que c'est ce que vous voulez? Je trouve préférable d'avoir un objectif en tête: "ce qui est dans ma branche qui n'est pas en amont", ou "ce qui est dans ma branche qui n'est pas en master". De plus, bien que git soit rapide à l'élagage, cela va devenir plus cher car vous avez plus de branches. J'ai un script que j'utilise que j'appelle "git missing" après la commande "missing" de bzr. Vous pouvez le trouver ici: github.com/jszakmeister/etc/blob/master/git-addons/git-missing .
John Szakmeister

1
En fait, j'ai besoin de cela pour un crochet post-réception, donc "master" ne sera pas toujours la branche à exclure
dimirc

Oui, le doublon mentionné par StarPinkER a bien fonctionné pour moi: git log $ (git merge-base HEAD branch) .. branch
charo

Réponses:


165

D'après ce que cela semble que vous devriez utiliser cherry:

git cherry -v develop mybranch

Cela montrerait tous les commits contenus dans mybranch , mais PAS dans develop . Si vous laissez la dernière option ( mybranch ), elle comparera la branche actuelle à la place.

Comme l'a souligné VonC, vous comparez TOUJOURS votre branche à une autre branche, alors connaissez vos branches, puis choisissez celle à comparer.


4
C'est exactement ce dont j'avais besoin, mais il semble qu'il devrait y avoir une commande plus intuitive (oui, même dans le monde de Git) pour cela.
Seth

12
Vous pouvez également git cherry -v mastercomparer votre branche actuelle avec la branche principale.
Pithikos

2
Le danger d'utiliser git cherry est que les validations ne sont appariées que si leurs différences de fichier sont identiques entre les branches. Si une quelconque fusion a été effectuée qui rendrait les différences différentes entre une branche et l'autre, alors git cherry les voit comme des commits différents.
Ben

Cela me donne juste fatal: Unknown commit mybranch.
Matt Arnold

1
@MattArnold vous devez changer le texte "develop" et "mybranch" en branches qui existent sur votre repo
Smilie

40

MAIS je voudrais éviter d'avoir à connaître les noms des autres branches.

Je ne pense pas que ce soit possible: une branche dans Git est toujours basée sur une autre ou au moins sur une autre commit, comme expliqué dans " git diff ne montre pas assez ":

entrez la description de l'image ici

Vous avez besoin d'un point de référence pour que votre journal affiche les bons commits.

Comme mentionné dans " GIT - D'où je me suis branchée? ":

les branches sont simplement des pointeurs vers certains commits dans un DAG

Donc, même s'il git log master..mybranchs'agit d'une seule réponse, elle afficherait toujours trop de validations, si elle mybranchest basée sur myotherbranch, elle-même basée sur master.

Afin de trouver cette référence (l'origine de votre branche), vous pouvez uniquement analyser les validations et voir dans quelle branche elles se trouvent, comme indiqué dans:


26

J'ai enfin trouvé le moyen de faire ce que le PO voulait. C'est aussi simple que:

git log --graph [branchname]

La commande affichera toutes les validations accessibles à partir de la branche fournie au format graphique. Mais, vous pouvez facilement filtrer toutes *les validations de cette branche en consultant le graphique des validations dont le premier caractère est dans la ligne de validation.

Par exemple, regardons l'extrait du git log --graph masterdépôt GakeHub sur cakephp ci-dessous:

D:\Web Folder\cakephp>git log --graph master
*   commit 8314c2ff833280bbc7102cb6d4fcf62240cd3ac4
|\  Merge: c3f45e8 0459a35
| | Author: José Lorenzo Rodríguez <lorenzo@users.noreply.github.com>
| | Date:   Tue Aug 30 08:01:59 2016 +0200
| |
| |     Merge pull request #9367 from cakephp/fewer-allocations
| |
| |     Do fewer allocations for simple default values.
| |
| * commit 0459a35689fec80bd8dca41e31d244a126d9e15e
| | Author: Mark Story <mark@mark-story.com>
| | Date:   Mon Aug 29 22:21:16 2016 -0400
| |
| |     The action should only be defaulted when there are no patterns
| |
| |     Only default the action name when there is no default & no pattern
| |     defined.
| |
| * commit 80c123b9dbd1c1b3301ec1270adc6c07824aeb5c
| | Author: Mark Story <mark@mark-story.com>
| | Date:   Sun Aug 28 22:35:20 2016 -0400
| |
| |     Do fewer allocations for simple default values.
| |
| |     Don't allocate arrays when we are only assigning a single array key
| |     value.
| |
* |   commit c3f45e811e4b49fe27624b57c3eb8f4721a4323b
|\ \  Merge: 10e5734 43178fd
| |/  Author: Mark Story <mark@mark-story.com>
|/|   Date:   Mon Aug 29 22:15:30 2016 -0400
| |
| |       Merge pull request #9322 from cakephp/add-email-assertions
| |
| |       Add email assertions trait
| |
| * commit 43178fd55d7ef9a42706279fa275bb783063cf34
| | Author: Jad Bitar <jadbitar@mac.com>
| | Date:   Mon Aug 29 17:43:29 2016 -0400
| |
| |     Fix `@since` in new files docblocks
| |

Comme vous pouvez le voir, seulement commits 8314c2ff833280bbc7102cb6d4fcf62240cd3ac4et c3f45e811e4b49fe27624b57c3eb8f4721a4323bavoir *le premier caractère dans la validation des lignes. Ces validations proviennent de la branche principale tandis que les quatre autres proviennent d'autres branches.


11

La commande shell suivante devrait faire ce que vous voulez:

git log --all --not $(git rev-list --no-walk --exclude=refs/heads/mybranch --all)

Avertissements

Si vous avez mybranchvérifié, la commande ci-dessus ne fonctionnera pas. C'est parce que les validations mybranchsont également accessibles par HEAD, donc Git ne considère pas les validations comme uniques à mybranch. Pour le faire fonctionner lorsqu'il mybranchest extrait, vous devez également ajouter une exclusion pour HEAD:

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=HEAD \
    --all)

Cependant, vous ne devez pas exclure HEADsauf si le mybranchest extrait, sinon vous risquez d'afficher des validations qui ne sont pas exclusives à mybranch.

De même, si vous avez une branche distante nommée origin/mybranchqui correspond à la mybranchbranche locale , vous devrez l'exclure:

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=refs/remotes/origin/mybranch \
    --all)

Et si la branche distante est la branche par défaut du référentiel distant (généralement vrai uniquement pour origin/master), vous devrez également exclure origin/HEAD:

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=refs/remotes/origin/mybranch \
    --exclude=refs/remotes/origin/HEAD \
    --all)

Si vous avez extrait la branche et qu'il y a une branche distante et que la branche distante est la valeur par défaut pour le référentiel distant, vous finissez par exclure beaucoup:

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=HEAD
    --exclude=refs/remotes/origin/mybranch \
    --exclude=refs/remotes/origin/HEAD \
    --all)

Explication

La git rev-listcommande est une commande de bas niveau (plomberie) qui parcourt les révisions données et sauvegarde les identificateurs SHA1 rencontrés. Considérez-le comme équivalent, git logsauf qu'il ne montre que le SHA1 - pas de message de journal, pas de nom d'auteur, pas d'horodatage, rien de tout cela "fantaisiste".

L' --no-walkoption, comme son nom l'indique, empêche git rev-listde parcourir la chaîne d'ascendance. Donc, si vous tapez, git rev-list --no-walk mybranchil n'imprimera qu'un seul identifiant SHA1: l'identifiant du commit de tip de la mybranchbranche.

Les --exclude=refs/heads/mybranch --allarguments indiquent git rev-listde commencer à partir de chaque référence à l'exception de refs/heads/mybranch.

Ainsi, lorsque vous exécutez git rev-list --no-walk --exclude=refs/heads/mybranch --all, Git affiche l'identifiant SHA1 de la validation de pointe de chaque référence, à l'exception de refs/heads/mybranch. Ces commits et leurs ancêtres sont les commits que vous ne vous intéresse en ce sont les commits vous ne pas voulez voir.

Les autres validations sont celles que vous souhaitez voir, nous collectons donc la sortie de git rev-list --no-walk --exclude=refs/heads/mybranch --allet demandons à Git de tout montrer sauf ces validations et leurs ancêtres.

L' --no-walkargument est nécessaire pour les grands référentiels (et est une optimisation pour les petits référentiels): sans lui, Git devrait imprimer, et le shell devrait collecter (et stocker en mémoire) beaucoup plus d'identifiants de validation que nécessaire. Avec un grand référentiel, le nombre de validations collectées pourrait facilement dépasser la limite d'argument de ligne de commande du shell.

Git bug?

Je m'attendais à ce que les éléments suivants fonctionnent:

git log --all --not --exclude=refs/heads/mybranch --all

mais ce n'est pas le cas. Je suppose que c'est un bug dans Git, mais c'est peut-être intentionnel.


Belle explication. +1
VonC

5
Je suis venu ici pour savoir comment faire Mercurial hg log -b <branch>. Je ne comprends pas pourquoi les gens disent que git est hostile. / s
weberc2

Je ne sais pas pourquoi git log --all --not --exclude=refs/heads/mybranch --allne fonctionne pas, mais le git log refs/heads/mybranch --not --exclude=refs/heads/mybranch --allfait, avec les mêmes mises en garde concernant l'exclusion de HEAD et de l'origine.
Ben C

8

Réponse rapide:

git log $(git merge-base master b2)..HEAD

Disons:

  1. Que vous avez une branche maître

  2. Faites quelques commits

  3. Vous avez créé une branche nommée b2

  4. Faites git log -n1; l'ID de validation est la base de fusion entre b2 et master

  5. Faites quelques commits en b2

  6. git log affichera l'historique de vos journaux de b2 et master

  7. Utilisez la plage de commit, si vous n'êtes pas familier avec le concept, je vous invite à le google ou à empiler overflow-it,

    Pour votre contexte réel, vous pouvez faire par exemple

    git log commitID_FOO..comitID_BAR
    

    Le ".." est l'opérateur de plage pour la commande log.

    Cela signifie, sous une forme simple, donnez-moi tous les journaux plus récents que commitID_FOO ...

  8. Regardez le point # 4, la base de fusion

    Alors: git log COMMITID_mergeBASE..HEADvous montrera la différence

  9. Git peut récupérer la base de fusion pour vous comme ceci

    git merge-base b2 master
    
  10. Enfin, vous pouvez faire:

    git log $(git merge-base master b2)..HEAD
    

4

Vous pouvez essayer quelque chose comme ceci:

#!/bin/bash

all_but()
{
    target="$(git rev-parse $1)"
    echo "$target --not"
    git for-each-ref --shell --format="ref=%(refname)" refs/heads | \
    while read entry
    do
        eval "$entry"

        test "$ref" != "$target" && echo "$ref"
    done
}

git log $(all_but $1)

Ou, en empruntant à la recette du manuel de l'utilisateur de Git :

#!/bin/bash
git log $1 --not $( git show-ref --heads | cut -d' ' -f2 | grep -v "^$1" )

+1. J'écrivais dans ma réponse que vous devez analyser les commits pour trouver l'origine de votre branche, et vous semblez l'avoir fait.
VonC

Avez-vous utilisé log --walk-reflogs? Je lis à propos de cette option et me donne les résultats dont j'ai besoin jusqu'à présent, (toujours en test)
dimirc

@dimirc Reflogs est une bête différente tous ensemble. Il enregistre les points de branchement au fil du temps, généralement à des fins de récupération. Je ne suis pas sûr de ce que vous faites dans votre hook post-réception mais peut-être que si vous l'expliquez, les gens pourraient fournir une réponse plus sensible à votre problème.
John Szakmeister

J'ai juste besoin d'analyser / vérifier tous les messages de validation en une seule fois. Le cas que je veux couvrir est si quelqu'un pousse plusieurs validations sur master et crée également une nouvelle branche avec plusieurs validations. Le hook post-réception doit vérifier les modifications effectuées pour les deux refs / branches, par exemple master et newbranch, j'ai besoin de connaître les limites de la nouvelle branche pour éviter d'analyser deux fois les messages de commit, car pourrait être commit du master.
dimirc

1
D'accord. Ensuite, je pense que l'approche ci-dessus que j'ai décrite est vraiment ce que vous voulez. Avec reflog, les entrées vont tomber après un certain temps, et je pense que cela vous causera des maux de tête. Vous voudrez peut-être aussi envisager d'utiliser git show-ref --tags.
John Szakmeister

4
git rev-list --exclude=master --branches --no-walk

énumérera les conseils de chaque branche qui ne l'est pas master.

git rev-list master --not $(git rev-list --exclude=master --branches --no-walk)

liste tous les commit de masterl'historique qui ne figurent dans aucun autre historique de branche.

Le séquençage est important pour les options qui configurent le pipeline de filtres pour la sélection de validation, il --branchesdoit donc suivre tous les modèles d'exclusion qu'il est censé appliquer, et --no-walkdoit suivre les filtres fournissant les validations. Rev-list n'est pas censé marcher.


4

Cela générera les validations sur la branche actuelle. Si un argument est passé, il ne produit que les hachages.

git_show_all_commits_only_on_this_branch

#!/bin/bash
function show_help()
{
  ME=$(basename $0)
  IT=$(cat <<EOF
  
  usage: $ME {NEWER_BRANCH} {OLDER_BRANCH} {VERBOSE}
  
  Compares 2 different branches, and lists the commits found only 
  in the first branch (newest branch). 

  e.g. 
  
  $ME         -> default. compares current branch to master
  $ME B1      -> compares branch B1 to master
  $ME B1 B2   -> compares branch B1 to B2
  $ME B1 B2 V -> compares branch B1 to B2, and displays commit messages
  
  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi

# Show commit msgs if any arg passed for arg 3
if [ "$3" ]
then
  OPT="-v"
fi

# get branch names
OLDER_BRANCH=${2:-"master"}
if [ -z "$1" ]
then
  NEWER_BRANCH=$(git rev-parse --abbrev-ref HEAD)
else
  NEWER_BRANCH=$1
fi

if [ "$NEWER_BRANCH" == "$OLDER_BRANCH" ]
then
  echo "  Please supply 2 different branches to compare!"
  show_help
fi

OUT=$(\git cherry $OPT $OLDER_BRANCH $NEWER_BRANCH)

if [ -z "$OUT" ]
then
  echo "No differences found. The branches $NEWER_BRANCH and $OLDER_BRANCH are in sync."
  exit;
fi

if [ "$OPT" == "-v" ]
then
  echo "$OUT"
else
  echo "$OUT" | awk '{print $2}'
fi

1
Cela a produit environ 100 messages de journal non pertinents pour moi.
Arlie Stephens

Hé @ArlieStephens - je l'ai essayé et cela semble toujours fonctionner pour moi? J'ai juste ajouté de l'aide et plus de messages d'erreur à ce qui précède. Dites-moi comment ça se passe!
Brad Parks

Intéressant. En regardant le code tel que vous l'avez maintenant, je pense qu'il peut être aussi simple que l'original en supposant que la branche qui m'importe est sortie de master. Avec le code actuel, j'aurais pu spécifier explicitement la branche parent. (IIRC, ma branche dev est issue d'une branche release, pas master.)
Arlie Stephens

@ArlieStephens - ouais je ne pense pas avoir changé de fonctionnalité .... Je l'ai mise à jour une fois de plus et j'ai rendu les documents un peu plus précis après quelques tests locaux ... et j'ai ajouté une option "verbeuse" qui était là avant, mais je ne l'ai pas doc
Brad Parks

3

J'utilise les commandes suivantes:

git shortlog --no-merges --graph --abbrev-commit master..<mybranch>

ou

git log --no-merges --graph --oneline --decorate master..<mybranch>

1

J'ai trouvé cette approche relativement facile.

Commander à la succursale et

  1. Courir

    git rev-list --simplify-by-decoration -2 HEAD
    

Cela ne fournira que deux SHA:

1) dernier commit de la branche [C1]

2) et commit parent au premier commit de la branche [C2]

  1. Maintenant, lancez

    git log --decorate --pretty=oneline --reverse --name-status <C2>..<C1>
    

Ici C1 et C2 sont deux chaînes que vous obtiendrez lorsque vous exécuterez la première commande. Mettez ces valeurs sans <> dans la deuxième commande.

Cela donnera la liste de l'historique des changements de fichiers dans la branche.


Si vous lisez les trois premières lignes de la question, vous verrez que l'auteur répertorie cette commande exacte et explique pourquoi ce n'est pas ce qu'ils recherchent
black_fm

Ah @black_fm J'ai fait quelques changements dans la réponse. Vous pouvez le voter si vous le jugez utile maintenant. :)
Mustkeem K

0

Dans ma situation, nous utilisons Git Flow et GitHub. Pour cela, il vous suffit de comparer votre branche de fonctionnalités avec votre branche de développement sur GitHub.

Il montrera les validations effectuées uniquement dans votre branche de fonctionnalité.

Par exemple:

https://github.com/your_repo/compare/develop...feature_branch_name


Je suis d'accord que lorsque vous vous retrouvez dans la situation "Je veux voir à quoi ressemblera une demande de pull", la meilleure solution est souvent d'ignorer gitet d'utiliser à la place GitHub pour simplement faire une demande de pull ou comparer les branches.
pkamb
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.