Comment voir quels commits dans une branche ne sont pas dans l'autre?

180

J'ai deux branches develet next. En développement, j'ai un nombre plus ou moins énorme de commits. Certains des commits sont pris en charge next. J'ai également ajouté quelques commits au suivant qui sont fusionnés devel.

Maintenant, j'aimerais voir ce qui manque next, afin de pouvoir tester les modifications en détail avant de les apporter next. Ma question est maintenant, comment puis-je voir quels commits sont dans develmais pas dans le suivant?

Sascha Effert
la source
votre titre est un peu trompeur, car ce que vous voulez comparer est la pointe des deux branches. et je suis venu ici à la recherche d'une solution à deux comparez les commits spécifiques (différents) de deux branches
thebugfinder
Dupliquer ?: stackoverflow.com/questions/1710894/...
reinierpost

Réponses:

210

La commande peu utilisée git cherryvous montre les commits qui n'ont pas encore été sélectionnés. La documentation pour git cherryest ici , mais, en bref, vous devriez simplement pouvoir faire:

git checkout devel
git cherry next

... et voir la sortie un peu comme ceci:

+ 492508acab7b454eee8b805f8ba906056eede0ff
- 5ceb5a9077ddb9e78b1e8f24bfc70e674c627949
+ b4459544c000f4d51d1ec23f279d9cdb19c1d32b
+ b6ce3b78e938644a293b2dd2a15b2fecb1b54cd9

Les commits qui commencent par +seront ceux que vous n'avez pas encore sélectionnés next. Dans ce cas, je n'avais sélectionné qu'un seul commit pour l'instant. Vous voudrez peut-être ajouter le -vparamètre à la git cherrycommande, afin qu'elle affiche également la ligne d'objet de chaque validation.

Mark Longair
la source
Super, c'est ce dont j'avais besoin. Ce serait également bien d'avoir une brève description des tests, mais je peux écrire ceci.
Sascha Effert
29
Vous n'avez pas besoin de le faire git checkout devel, vous pouvez simplement le faire git cherry next devel.
Robin Winslow
21
"Pourrait vouloir ajouter le -v" ? Cerise sans a, -vc'est comme lssans -la. ; -J
Slipp D. Thompson
1
Et vous ne sauriez pas comment cherrymarquer ou exclure des commits équivalents, n'est-ce pas? cherrysemble être une commande de plomberie, mais n'offre pas (ne semble pas) offrir de nombreuses options. Pour ce que je suis actuellement au milieu, git cherryme donne de faux positifs, mais @ sehe git log --cherry-pickexclut correctement les commits précédemment sélectionnés / rebasés.
Slipp D.Thompson
La documentation fournit un exemple concret: git-scm.com/docs/git-cherry#_concrete_example
ams
107

En outre, vous pouvez utiliser

git log --left-right --graph --cherry-pick --oneline devel...next

pour obtenir une belle liste de commits différents réels non partagés entre les branches.

Le mot clé est --cherry-pick

--cherry-pick

Omettez tout commit qui introduit le même changement qu'un autre commit de «l'autre côté» lorsque l'ensemble des commits est limité avec une différence symétrique. Par exemple, si vous avez deux branches, A et B, une façon habituelle de lister tous les commits sur un seul côté est avec --left-right, comme l'exemple ci-dessus dans la description de cette option. Il montre cependant les commits qui ont été sélectionnés à partir de l'autre branche (par exemple, "3rd on b" peut être sélectionné à partir de la branche A). Avec cette option, ces paires de validations sont exclues de la sortie.

Mise à jour Comme mentionné dans un commentaire, les versions récentes de git ont ajouté --cherry-mark:

--cherry-mark

Comme --cherry-pick (voir ci-dessous) mais marquez les validations équivalentes avec = plutôt que de les omettre, et les équivalents avec +.

sehe
la source
1
Cela n'a pas fonctionné pour moi. Ma version de git ne sait pas - une ligne, donc je l'ai supprimée. Ensuite, j'ai dû échanger devel et ensuite et cela a fonctionné. Très agréable!
Sascha Effert
@SaschaEffert: vous n'avez pas eu à changer de développement et suivant (remarquez TROIS points, pas DEUX). Cela dit, les choses peuvent être différentes si vous avez utilisé une ancienne version de git (?), Mais dans ce cas, vous auriez dû obtenir une erreur d'analyse de rev sur les trois points.
sehe
2
Pour le plaisir, j'ai découvert que la syntaxe rev-parse '...' (différence symétrique) avait été ajoutée en juillet 2006 et que la documentation la concernant avait été mise à jour en juin 2008 . La joie de l'open source!
sehe
1
'gls --first-parent --cherry-mark --left-only develop ... next' où gls est mon alias git log avec tout le joli formatage. cherry-mark montre à la fois les cerises cueillies et non cueillies sur cerises, mais les marque différemment.
angularsen
1
ajouter --no-
merges
51

Vous pouvez essayer de créer des sous-ensembles de journaux git:

git log --oneline devel ^next
Bryan Buckley
la source
4
C'est la meilleure solution à mon avis (la réponse de @ sehe montre également des commits dans next qui ne sont pas en développement - dans le contexte de l'OP, il n'y en a pas, mais dans le mien il y en a - utiliser --left-onlyaurait été mieux). Cependant, celui-ci peut être amélioré un peu en ajoutant --no-mergespour omettre les commits de fusion (par exemple, si une fonctionnalité ou une branche de correctif a été fusionnée (séparément) dans devel et next). À proprement parler, bien sûr, la résolution des conflits dans les fusions peut créer d'autres différences, mais ce n'est généralement pas le cas. L' --no-mergesoption peut également être utilement appliquée aux autres réponses.
Alex Dupuy
27

Que diriez-vous

git log next..devel

Le résultat est similaire à la réponse de Byran (ordre différent de commits) mais nos deux réponses produiront des commits différents entre les branches, plutôt que de montrer ce qui se trouve dans une branche et pas dans l'autre.

justingordon
la source
4
Vous pouvez également omettre la deuxième branche si vous êtes actuellement sur cette branche. iegit log next..
jmaxyz
btw 'git log next..devel' est différent de 'git log devel..next'
Eugene Kaurov
1

Pour obtenir la liste des commits qui n'ont pas été intégrés dans la branche de publication (suivante), vous pouvez utiliser:

git rev-list --reverse --pretty="TO_TEST %h (<%ae>) %s" --cherry-pick --right-only origin/release_branch...origin/development_branch | grep "^TO_TEST " > NotIntegratedYet.txt

Consultez git-rev-list pour plus d'informations.

Mihai
la source
la commande de cette réponse ne next...devel
Alex Dupuy
@AlexDupuy Yah, c'est une réponse plutôt trompeuse. Comme ce n'est pas non plus la réponse la plus simple et n'explique pas pourquoi cette approche serait meilleure, je suis -1 -sur.
Slipp D.Thompson
-1

@Mark Longair l'a cloué dans sa réponse ici , mais j'aimerais ajouter quelques informations supplémentaires.

Associé, et répondre à la question de savoir comment diviser une grande demande de tirage (PR), en particulier lorsque l'écrasement de vos validations est impossible en raison d'une ou plusieurs fusions de master dans votre feature_branch

Ma situation:
j'ai fait un gros feature_branchavec 30 commits et ouvert une Pull Request (PR) sur GitHub pour la fusionner master. La branche a masterchangé une tonne sous moi et a reçu 200 commits que je feature_branchn'avais pas. Pour résoudre les conflits que j'ai faits git checkout feature_branchet git merge masterpour fusionner masterles modifications apportées à mon feature_branch. J'ai choisi mergeplutôt que rebasesur le dernier maître, donc je devrais résoudre les conflits une seule fois au lieu de potentiellement 30 fois (une fois pour chacun de mes commits). Je ne voulais pas écraser mes 30 commits en 1 d'abord, puis rebaser sur le derniermastercar cela pourrait effacer l'historique des commentaires sur GitHub dans le PR. Donc, j'ai fusionné master dans ma branche de fonctionnalités et résolu les conflits une seule fois. Tout allait bien. Mon PR, cependant, était trop gros pour que mes collègues puissent l'examiner. J'avais besoin de le diviser. Je suis allé écraser mes 30 commits et OH NON! OÙ SONT-ELLES? ILS SONT TOUS INTERMÉLANGÉS AVEC masterles 200 commits récents maintenant parce que j'ai fusionné masterdans mon feature_branch! QUE FAIS-JE?

git cherryutilisation au cas où vous voudriez essayer git cherry-pickdes commits individuels:

git cherry à la rescousse (en quelque sorte)!

Pour voir tous les commits qui sont dans feature_branchmais PAS dans, masterje peux faire:

git checkout feature_branch
git cherry master

OU, je peux vérifier les commits de N'IMPORTE QUELLE branche sans m'assurer que je suis le feature_branchpremier en faisant git cherry [upstream_branch] [feature_branch], comme ceci. Encore une fois, cela vérifie pour voir quels commits SONT dans feature_branchmais ne sont PAS dans upstream_branch( masterdans ce cas):

git cherry master feature_branch

L'ajout -vmontre également les lignes d'objet du message de validation:

git cherry -v master

La redirection vers "word count" "-lines" ( wc -l) compte le nombre de commits:

git cherry master | wc -l

Vous pouvez comparer ce nombre au numéro de validation indiqué dans votre PR GithHub pour vous sentir mieux en sachant que git cherrycela fonctionne vraiment. Vous pouvez également comparer les hachages git un par un et voir qu'ils correspondent entre git cherryet GitHub. Notez que git cherryne compteront pas tous les commits de fusion où vous avez reportés masterdans feature_branch, mais GitHub. Donc, si vous voyez une petite différence dans le décompte, recherchez le mot "fusion" sur la page de validation de GitHub PR et vous verrez probablement que c'est le coupable qui n'apparaît pas git cherry. Ex: un commit intitulé "Fusionner la branche 'master' dans feature_branch" apparaîtra dans le GitHub PR mais pas lors de l'exécution git cherry master feature_branch. C'est bien et attendu.

Donc, maintenant j'ai un moyen de savoir quels diffs je pourrais vouloir choisir une nouvelle branche de fonctionnalités pour diviser ce diff: je peux utiliser git cherry master feature_branchlocalement, ou regarder les commits dans le GitHub PR.

Comment l'écrasement pourrait aider - si seulement nous pouvions écraser:

Une alternative, cependant, pour diviser mon gros diff est d' écraser tous mes 30 commits en un seul, de les patcher sur une nouvelle branche de fonctionnalité, de réinitialiser le commit du correctif, puis de l'utiliser git guipour ajouter des morceaux fichier par fichier, morceau par morceau, ou ligne par ligne. Une fois que j'ai une sous-fonctionnalité, je peux valider ce que j'ai ajouté puis vérifier une nouvelle branche, en ajouter d'autres, valider, vérifier une nouvelle branche, etc., jusqu'à ce que ma grande fonctionnalité soit divisée en plusieurs sous-fonctionnalités . Le problème est que mes 30 commits sont mélangés avec les 200 autres commits d'autres personnes en raison de mon git merge masterdans mon feature_branch, donc le rebasage est donc peu pratique, car je devrais passer au crible 230 commits pour réorganiser et écraser mes 30 commits.

Comment utiliser un fichier de correctif comme remplacement beaucoup plus facile de l'écrasement:

Une solution consiste simplement à obtenir un fichier de correctif contenant un «équivalent squash» de mes 30 commits, à le patcher sur un nouveau fork de master(une nouvelle sous-branche de fonctionnalité) et à travailler à partir de là, comme suit:

git checkout feature_branch
# ensure I have the latest changes from master merged into feature_branch
git merge master 
# Obtain a patch file, which is the equivalent of a squash of my 30 commits into 1 commit:
git diff master..feature_branch > ~/mypatch.patch
git checkout master
# Create a new, sub-feature branch
git checkout -b feature_branch2
# Patch the 30 commit patch file onto it:
git apply ~/mypatch.patch

Maintenant, mon correctif de 30 commit est appliqué localement, mais non mis en scène et non validé.

Maintenant, utilisez git guipour ajouter des fichiers, des morceaux et / ou des lignes et briser votre gros PR ou "diff":

Notez que si vous ne l'avez pas git gui, vous pouvez facilement l'installer dans Ubuntu avec sudo apt install git-gui.

Je peux maintenant exécuter git guiet commencer à ajouter des fichiers, des morceaux et / ou des lignes (en cliquant avec le bouton droit dans le programme git GUI), et diviser la branche de 30 fonctionnalités de validation en sous-branches comme décrit ci-dessus, en ajoutant, en validant, puis en forçant à plusieurs reprises une nouvelle branche de fonctionnalité et répéter ce cycle jusqu'à ce que toutes les modifications aient été ajoutées à une sous-branche de fonctionnalité et que ma fonctionnalité 30-commit soit divisée avec succès en 3 ou 4 sous-fonctionnalités. Je peux maintenant ouvrir un PR distinct pour chacune de ces sous-fonctionnalités, et elles seront plus faciles à examiner pour mon équipe.

Références:

  1. Créez un fichier correctif ou diff à partir du référentiel git et appliquez-le à un autre référentiel git différent
Gabriel Staples
la source
J'avais besoin de faire référence à cette réponse aujourd'hui, mais je n'ai pas pu la trouver rapidement. Heureusement, il y avait un vote négatif pour m'aider à trouver les choses plus faciles, donc un simple clic sur l'icône de la coupe des récompenses en haut à droite de l'écran montrait où j'ai récemment perdu 2 points, et en cliquant dessus, cela m'a ramené ici où je peux maintenant référence ma propre réponse ici! J'espère que je n'obtiens plus de votes négatifs, mais à ceux qui sont défavorables, merci pour le service qui m'a accidentellement aidé!
Gabriel Staples