Wie kann man sehen, welche Commits in einem Zweig nicht im anderen sind?

180

Ich habe zwei Zweige develund next. In der Entwicklung habe ich eine mehr oder weniger große Anzahl von Commits. Einige der Commits sind Kirsche gepflückt next. Außerdem habe ich als nächstes einige Commits hinzugefügt, die zusammengeführt werden devel.

Jetzt möchte ich sehen, was fehlt next, damit ich die Änderungen im Detail testen kann, bevor ich sie anbringe next. Meine Frage ist jetzt, wie kann ich sehen, welche Commits in, develaber nicht in den nächsten enthalten sind?

Sascha Effert
quelle
Ihr Titel ist etwas irreführend, da Sie die Spitze beider Zweige vergleichen möchten. und ich kam hierher, um nach einer Lösung zu suchen, bei der zwei spezifische (unterschiedliche) Commits von zwei Zweigen vergleichen
thebugfinder
Duplizieren?: Stackoverflow.com/questions/1710894/…
reinierpost

Antworten:

210

Der wenig verwendete Befehl git cherryzeigt Ihnen die Commits, die noch nicht ausgewählt wurden. Die Dokumentation für git cherryist hier , aber kurz gesagt, Sie sollten nur in der Lage sein:

git checkout devel
git cherry next

... und sehen die Ausgabe ein bisschen so:

+ 492508acab7b454eee8b805f8ba906056eede0ff
- 5ceb5a9077ddb9e78b1e8f24bfc70e674c627949
+ b4459544c000f4d51d1ec23f279d9cdb19c1d32b
+ b6ce3b78e938644a293b2dd2a15b2fecb1b54cd9

Die Commits, mit +denen Sie beginnen , sind diejenigen, in die Sie sich noch nicht eingemischt haben next. In diesem Fall hatte ich bisher nur ein Commit ausgewählt. Möglicherweise möchten Sie den -vParameter zum git cherryBefehl hinzufügen , damit auch die Betreffzeile jedes Commits ausgegeben wird.

Mark Longair
quelle
Großartig, das was ich brauchte. Es wäre auch schön, eine kurze Beschreibung der Tests zu erhalten, aber ich kann dies skripten.
Sascha Effert
29
Sie müssen nicht git checkout devel, Sie können es einfach tun git cherry next devel.
Robin Winslow
21
"Vielleicht möchten Sie das hinzufügen -v" ? Kirsche ohne a -vist wie lsohne -la. ; -J
Slipp D. Thompson
1
Und Sie würden nicht wissen cherry, wie Sie gleichwertige Commits markieren oder ausschließen können, oder? cherryscheint ein Sanitärbefehl zu sein, bietet aber nicht viele Optionen. Für das, was ich gerade in der Mitte bin git cherry, erhalte ich falsch positive Ergebnisse, aber @ sehe git log --cherry-pickschließt die zuvor ausgewählten / neu basierten Commits korrekt aus.
Slipp D. Thompson
Die Dokumentation bietet ein konkretes Beispiel: git-scm.com/docs/git-cherry#_concrete_example
ams
107

Auch können Sie verwenden

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

eine schöne Liste zu bekommen , tatsächlich unterschiedliche Commits nicht zwischen den Zweigen geteilt.

Das operative Wort ist --cherry-pick

--cherry-pick

Lassen Sie jedes Commit aus, das dieselbe Änderung wie ein anderes Commit auf der "anderen Seite" einführt, wenn die Anzahl der Commits mit symmetrischen Unterschieden begrenzt ist. Wenn Sie beispielsweise zwei Zweige haben, A und B, können Sie alle Commits normalerweise nur auf einer Seite auflisten, indem Sie --left-right verwenden, wie im obigen Beispiel in der Beschreibung dieser Option. Es werden jedoch die Commits angezeigt, die aus dem anderen Zweig ausgewählt wurden (z. B. kann "3rd on b" aus Zweig A ausgewählt werden). Mit dieser Option werden solche Commit-Paare von der Ausgabe ausgeschlossen.

Update Wie in einem Kommentar erwähnt, haben aktuelle Versionen von git hinzugefügt --cherry-mark:

--cherry-mark

Wie --cherry-pick (siehe unten), aber markieren Sie gleichwertige Commits mit =, anstatt sie wegzulassen, und ungleiche Commits mit +.

sehe sehen
quelle
1
Das hat bei mir nicht funktioniert. Meine Version von git kennt --one-line nicht, deshalb habe ich es entfernt. Dann musste ich mich austauschen und als nächstes und es funktionierte. Sehr schön!
Sascha Effert
@SaschaEffert: Sie mussten nicht zwischen Entwicklung und Weiter wechseln (beachten Sie DREI Punkte, nicht ZWEI). Das heißt, die Dinge können anders sein, wenn Sie eine alte Version von git (?) Verwendet haben, aber in diesem Fall hätten Sie einen Rev-Parse-Fehler auf den drei Punkten bekommen sollen.
sehe
2
Zum Spaß habe ich herausgefunden, dass die Rev-Parse-Syntax '...' (symmetrischer Unterschied) im Juli 2006 hinzugefügt und die Dokumentation dafür im Juni 2008 aktualisiert wurde . Die Freude an Open Source!
sehe
1
'gls --first-parent --cherry-mark --left-only Develop ... next' wobei gls mein Git-Log-Alias ​​mit all der hübschen Formatierung ist. Cherry-Mark zeigt sowohl die von Cherry gepflückten als auch die nicht von Cherry gepflückten Commits bei der Entwicklung an, markiert sie jedoch unterschiedlich.
Angularsen
1
add
no-merges
51

Sie könnten versuchen, Git-Log-Teilmengen zu erstellen:

git log --oneline devel ^next
Bryan Buckley
quelle
4
Dies ist meiner Meinung nach die beste Lösung (die Antwort von @ sehe zeigt auch Commits im nächsten, die nicht in der Entwicklung sind - im Kontext des OP gibt es keine, aber in meinem gibt es - --left-onlywäre die Verwendung besser gewesen). Dieser kann jedoch ein wenig verbessert werden, indem hinzugefügt wird --no-merges, um Zusammenführungs-Commits wegzulassen (z. B. wenn ein Feature oder ein Hotfix-Zweig (separat) in devel und next zusammengeführt wurde). Genau genommen kann die Konfliktlösung bei Zusammenführungen natürlich zu anderen Unterschieden führen, aber das ist normalerweise nicht der Fall. Die --no-mergesOption kann sinnvollerweise auch auf die anderen Antworten angewendet werden.
Alex Dupuy
27

Wie wäre es mit

git log next..devel

Das Ergebnis ähnelt Byrans Antwort (unterschiedliche Reihenfolge der Festschreibungen), aber unsere beiden Antworten führen zu Festschreibungen, die zwischen den Zweigen unterschiedlich sind, und zeigen nur, was sich in einem Zweig und nicht in dem anderen befindet.

Justingordon
quelle
4
Sie können den zweiten Zweig auch weglassen, wenn Sie sich gerade in diesem Zweig befinden. dhgit log next..
jmaxyz
Übrigens unterscheidet sich 'git log next..devel' von 'git log devel..next'
Eugene Kaurov
1

Um die Liste der Commits zu erhalten, die nicht in den Release-Zweig (weiter) integriert wurden, können Sie Folgendes verwenden:

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

Überprüfen Sie git-rev-list für weitere Informationen.

Mihai
quelle
Der Befehl dieser Antwort fehlt die fraglichen Zweige, dhnext...devel
Alex Dupuy
@AlexDupuy Yah, es ist eine ziemlich halbherzige Antwort. Da es auch nicht die einfachste Antwort ist und nicht erklärt, warum dieser Ansatz besser wäre, bin ich -1 -ing es.
Slipp D. Thompson
-1

@ Mark Longair hat es in seiner Antwort hier festgehalten , aber ich möchte einen zusätzlichen Einblick hinzufügen.

Die Beantwortung der Frage, wie eine große Pull-Anforderung (PR) aufgelöst werden kann, insbesondere wenn Ihre Commits gequetscht werden, ist aufgrund einer oder mehrerer Zusammenführungen von Master in Ihrer feature_branch unpraktisch

Meine Situation:
Ich habe feature_branchmit 30 Commits ein großes Ergebnis erzielt und eine Pull-Anfrage (PR) auf GitHub geöffnet, um sie zusammenzuführen master. Branch masterwechselte eine Tonne unter mir und erhielt 200 Commits, die ich feature_branchnicht hatte. Um Konflikte zu lösen, die ich gemacht habe, git checkout feature_branchund git merge masterum die masterÄnderungen in meine zu integrieren feature_branch. Ich habe mich dafür entschieden, mergeanstattrebase auf neuesten Master , damit ich zu der Lösung von Konflikten nur ein einziges Mal statt potenziell 30 Mal (einmal für jedes meiner Commits) haben würde. Ich wollte meine 30 Commits nicht zuerst in 1 zerquetschen und dann auf die neuesten zurücksetzenmasterweil das GitHub Review Kommentarverlauf in der PR wegwischen könnte. Also habe ich Master in meinem Feature-Zweig zusammengeführt und Konflikte 1 Mal gelöst. Alles war gut. Meine PR war jedoch zu groß, als dass meine Kollegen sie überprüfen könnten. Ich musste es aufteilen. Ich ging meine 30 Commits zu quetschen und OH NEIN! WO SIND SIE? SIE SIND ALLE MIT DEN master200 letzten Commits vermischt , weil ich mich masterin meine verschmolzen habe feature_branch! WAS MACHE ICH?

git cherryVerwendung für den Fall, dass Sie versuchen möchten, git cherry-pickeinzelne Commits durchzuführen:

git cherry zur Rettung!

Um alle Commits zu sehen, die in, feature_branchaber NICHT in sind, masterkann ich Folgendes tun:

git checkout feature_branch
git cherry master

OR, kann ich Festschreibungen von jeder Filiale überprüfen , ohne sicherzustellen , ich bin auf dem feature_branchersten , indem Sie git cherry [upstream_branch] [feature_branch], wie diese. Auch hier wird überprüft, welche Commits enthalten feature_branchsind, aber NICHT upstream_branch( masterin diesem Fall):

git cherry master feature_branch

Beim Hinzufügen werden -vauch die Betreffzeilen der Festschreibungsnachricht angezeigt:

git cherry -v master

Das Piping zu "word count" "-lines" ( wc -l) zählt, wie viele Commits es gibt:

git cherry master | wc -l

Sie können diese Anzahl mit der in Ihrem GithHub PR angezeigten Commit-Nummer vergleichen, um besser zu wissen, dass sie git cherrywirklich funktioniert. Sie können die Git-Hashes auch einzeln vergleichen und sehen, ob sie zwischen git cherryund GitHub übereinstimmen . Bitte beachte , dass git cherryalle Merge Commits nicht zählen, wo Sie verschmolzen masterzu feature_branch, aber GitHub WILL. Wenn Sie also eine kleine Diskrepanz in der Anzahl sehen, durchsuchen Sie die GitHub PR-Commit-Seite nach dem Wort "Merge" und Sie werden wahrscheinlich sehen, dass dies der Schuldige ist, der nicht in angezeigt wird git cherry. Beispiel: Ein Commit mit dem Titel "Zweig 'Master' in feature_branch zusammenführen" wird in GitHub PR angezeigt, jedoch nicht, wenn Sie ausgeführt werden git cherry master feature_branch. Das ist in Ordnung und wird erwartet.

Jetzt habe ich also die Möglichkeit herauszufinden, welche Unterschiede ich möglicherweise in einem neuen Feature-Zweig auswählen möchte, um diesen Unterschied aufzuteilen: Ich kann sie git cherry master feature_branchlokal verwenden oder mir die Commits in GitHub PR ansehen.

Wie Quetschen helfen könnte - wenn wir nur quetschen könnten:

Eine Alternative, um meinen großen Unterschied aufzuteilen, besteht darin, alle 30 meiner Commits in einen zu zerquetschen, diesen auf einen neuen Feature-Zweig zu patchen, den Patch-Commit sanft zurückzusetzen und dann git guiTeile Datei für Datei, Block für Block oder hinzuzufügen Zeile für Zeile. Sobald ich eine Unterfunktion erhalten habe, kann ich festschreiben, was ich hinzugefügt habe, und dann einen neuen Zweig auschecken, weitere hinzufügen, festschreiben, eine neue Verzweigung auschecken usw., bis meine große Funktion in mehrere Unterfunktionen aufgeteilt ist . Das Problem ist , dass mein 30 Commits mit den anderen 200 Commits von anderen Menschen verwirbelt werden aufgrund meiner git merge masterin meiner feature_branch, so Rebasieren daher nicht praktikabel ist, wie ich durch 230 Commits Nachbestellung sichten müss und zerquetschen mein 30 Commits.

So verwenden Sie eine Patch-Datei als viel einfacheren Ersatz für das Quetschen:

Eine Problemumgehung besteht darin, einfach eine Patch-Datei zu erhalten, die ein "Squash-Äquivalent" aller 30 meiner Commits enthält, sie auf einen neuen masterZweig (einen neuen Unter-Feature-Zweig) zu patchen und von dort aus wie folgt zu arbeiten:

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

Jetzt habe ich meinen 30-Commit-Patch alle lokal angewendet, aber nicht bereitgestellt und nicht festgeschrieben.

Verwenden Sie jetzt git gui, um Dateien, Chunks und / oder Zeilen hinzuzufügen und Ihre große PR oder "diff" aufzubrechen:

Beachten Sie git gui, dass Sie es problemlos in Ubuntu installieren können , wenn Sie es nicht haben sudo apt install git-gui.

Ich kann jetzt git guiDateien, Blöcke und / oder Zeilen ausführen und hinzufügen (indem ich mit der rechten Maustaste in das Git-GUI-Programm klicke) und den Zweig mit 30 Festschreibungsfunktionen wie oben beschrieben in Unterzweige aufteilen, wiederholt hinzufügen, festschreiben und dann gabeln Ein neuer Feature-Zweig und das Wiederholen dieses Zyklus, bis alle Änderungen zu einem Unter-Feature-Zweig hinzugefügt wurden und mein 30-Commit-Feature erfolgreich in 3 oder 4 Unter-Features aufgeteilt wurde. Ich kann jetzt für jede dieser Unterfunktionen eine separate PR eröffnen, die für mein Team leichter zu überprüfen ist.

Verweise:

  1. Erstellen Sie eine Patch- oder Diff-Datei aus dem Git-Repository und wenden Sie sie auf ein anderes Git-Repository an
Gabriel Staples
quelle
Ich musste heute auf diese Antwort verweisen, konnte sie aber nicht schnell finden. Glücklicherweise gab es eine Abwertung, die mir dabei half, es einfacher zu finden. Ein einfacher Klick auf das Award-Cup-Symbol oben rechts auf dem Bildschirm zeigte, wo ich kürzlich 2 Punkte verloren habe, und ein Klick darauf brachte mich hierher zurück, wo ich kann Verweise jetzt hier auf meine eigene Antwort! Hoffentlich bekomme ich keine Downvotes mehr, aber an den Downvoter, danke für den Service, der mir versehentlich geholfen hat!
Gabriel Staples