it-swarm.com.de

Warum legt Squash Git Commits für Pull-Anfragen fest?

Warum zieht jedes ernsthafte Github-Repo, das ich mache, Anfragen, damit ich meine Commits zu einem einzigen Commit zusammenfasse?

Ich dachte, das Git-Protokoll wäre da, damit Sie Ihre gesamte Historie überprüfen und genau sehen können, welche Änderungen wo passiert sind, aber wenn Sie es zerquetschen, wird es aus der Historie herausgezogen und alles in einem Commit zusammengefasst. Was ist der Sinn?

Dies scheint auch gegen das Mantra "früh und oft festschreiben" zu verstoßen.

221
hamstar

Damit Sie eine klare und präzise Git-Historie haben, die die vorgenommenen Änderungen und die Gründe dafür klar und einfach dokumentiert.

Zum Beispiel könnte ein typisches 'unquashed' Git-Protokoll für mich wie folgt aussehen:

7hgf8978g9... Added new slideshow feature, JIRA # 848394839
85493g2458... Fixed slideshow display issue in ie
gh354354gh... wip, done for the week
789fdfffdf... minor alignment issue
787g8fgf78... hotfix for #5849564648
9080gf6567... implemented feature # 65896859
gh34839843... minor fix (typo) for 3rd test

Was für ein Chaos!

Während ein sorgfältig verwaltetes und zusammengeführtes Git-Protokoll mit einem kleinen zusätzlichen Fokus auf die Nachrichten dafür aussehen könnte:

7hgf8978g9... 8483948393 Added new slideshow feature
787g8fgf78... 5849564648 Hotfix for Android display issue
9080gf6567... 6589685988 Implemented pop-up to select language

Ich denke, Sie können den Sinn des Quetschens von Commits allgemein erkennen, und das gleiche Prinzip gilt für Pull-Anforderungen - Lesbarkeit des Verlaufs. Sie können auch zu a hinzufügen Festschreibungsprotokoll, das bereits Hunderte oder sogar Tausende von Festschreibungen enthält. Dies hilft dabei, die wachsende Geschichte kurz und prägnant zu halten.

Sie möchten früh und oft festlegen. Es ist aus vielen Gründen eine bewährte Methode. Ich stelle fest, dass dies dazu führt, dass ich häufig Commits habe, die "abwischen" (in Arbeit) oder "Teil A erledigt" oder "Tippfehler, geringfügige Korrektur" sind, wobei ich Git verwende, um mir bei der Arbeit zu helfen und mir Arbeitspunkte zu geben Ich kann zurückkehren, wenn der folgende Code nicht funktioniert, während ich Fortschritte mache, um die Dinge zum Laufen zu bringen. Ich brauche oder möchte diesen Verlauf jedoch nicht als Teil des endgültigen Git-Verlaufs, damit ich meine Commits quetschen kann. Beachten Sie jedoch die nachstehenden Hinweise, was dies für einen Entwicklungszweig im Vergleich zum Master bedeutet.

Wenn es wichtige Meilensteine ​​gibt, die unterschiedliche Arbeitsphasen darstellen, ist es immer noch in Ordnung, mehr als ein Commit pro Feature/Aufgabe/Fehler durchzuführen. Dies kann jedoch häufig die Tatsache hervorheben, dass das in der Entwicklung befindliche Ticket "zu groß" ist und in kleinere Teile zerlegt werden muss, die eigenständig sein können, zum Beispiel:

8754390gf87... Implement feature switches

scheint wie "1 Stück Arbeit". Entweder existieren sie oder sie existieren nicht! Es scheint keinen Sinn zu machen, es auszubrechen. Die Erfahrung hat mir jedoch gezeigt, dass (abhängig von der Größe und Komplexität des Unternehmens) ein detaillierterer Pfad sein kann:

fgfd7897899... Add field to database, add indexes and a trigger for the dw group
9458947548g... Add 'backend' code in controller for when id is passed in url.
6256ac24426... Add 'backend' code to make field available for views.
402c476edf6... Add feature to UI

Kleine Teile bedeuten einfachere Codeüberprüfungen, einfachere Komponententests, bessere Qa-Möglichkeiten, bessere Ausrichtung auf das Prinzip der Einzelverantwortung usw.

Für die praktischen Aspekte, wann solche Kürbisse tatsächlich ausgeführt werden sollen, gibt es grundsätzlich zwei unterschiedliche Phasen, die über einen eigenen Workflow verfügen

  • ihre Entwicklung, z. Anfragen ziehen
  • ihre Arbeit wurde dem Hauptzweig hinzugefügt, z. Meister

Während Ihrer Entwicklung verpflichten Sie sich "früh und oft" und mit schnellen "Einweg" -Nachrichten. Möglicherweise möchten Sie hier manchmal quetschen, z. Quetschen in Wip- und ToDo-Nachrichten-Commits. Innerhalb des Zweigs ist es in Ordnung, mehrere Commits beizubehalten, die unterschiedliche Schritte darstellen, die Sie in der Entwicklung unternommen haben. Die meisten Squashes, die Sie auswählen, sollten sich in diesen Feature-Zweigen befinden, während sie entwickelt werden und bevor sie zum Master zusammengeführt werden.
Wenn Sie dem Hauptleitungszweig hinzufügen, möchten Sie, dass die Commits präzise und gemäß dem vorhandenen Hauptleitungsverlauf korrekt formatiert werden. Dies kann die Ticket Tracker-System-ID umfassen, z. JIRA wie in Beispielen gezeigt. Squashing gilt hier nicht wirklich, es sei denn, Sie möchten mehrere unterschiedliche Commits für den Master "zusammenrollen". Normalerweise nicht.

Verwenden von --no-ff Beim Zusammenführen mit dem Master wird ein Commit für die Zusammenführung verwendet und der Verlauf (in der Verzweigung) beibehalten. Einige Organisationen halten dies für eine bewährte Methode. Weitere Informationen finden Sie unter https://stackoverflow.com/q/9069061/631619 Sie sehen den praktischen Effekt auch in git log wo ein --no-ff commit ist das letzte Commit am oberen Rand von HEAD (wenn gerade erledigt), während ohne --no-ff Je nach Datum und anderen Verpflichtungen kann es weiter unten in der Geschichte liegen.

168
Michael Durrant

Da sich die Person, die eine PR erstellt, häufig um den Nettoeffekt der Commits kümmert, "hinzugefügtes Feature X", nicht um die "Basisvorlagen, Bugfix-Funktion X, Add-Funktion Y, feste Tippfehler in Kommentaren, angepasste Datenskalierungsparameter, Hashmap-Leistung besser als Liste "... Detaillierungsgrad

Wenn Sie der Meinung sind, dass Ihre 16 Commits am besten durch 2 Commits und nicht durch 1 "Feature X hinzugefügt, Z neu berücksichtigt, um X zu verwenden" dargestellt werden, ist es wahrscheinlich in Ordnung, einen PR mit 2 Commits vorzuschlagen, aber dann ist es möglicherweise am besten, einen Vorschlag zu machen In diesem Fall 2 separate Prs (wenn das Repo immer noch auf Single Commit Prs besteht)

Dies widerspricht nicht dem Mantra "Früh festschreiben und häufig festschreiben", wie in Ihrem Repo, während Sie sich weiterentwickeln, haben Sie immer noch die detaillierten Details, sodass Sie nur eine minimale Chance haben, Arbeit zu verlieren, und andere Personen können dies überprüfen/ziehen/vorschlagen PRs gegen Ihre Arbeit, während der neue PR entwickelt wird.

27
Andrew Hill

Der Hauptgrund von dem, was ich sehen kann, ist folgender:

  • Die GitHub-Benutzeroberfläche zum Zusammenführen von Pull-Anforderungen (Oktober 2015) ermöglicht es Ihnen derzeit nicht, die erste Zeile der Festschreibungsnachricht zu bearbeiten, sodass Merge pull request #123 from joebloggs/fix-snafoo
  • Die GitHub-Benutzeroberfläche zum Durchsuchen des Festschreibungsverlaufs ermöglicht es Ihnen derzeit nicht, den Verlauf des Zweigs aus der Sicht von --first-parent Anzuzeigen
  • Die GitHub-Benutzeroberfläche zum Betrachten der Schuld an einer Datei erlaubt es Ihnen derzeit nicht, die Schuld der Datei unter dem Gesichtspunkt --first-parent Anzuzeigen (beachten Sie, dass dies nur in Git 2.6.2 behoben wurde, also konnten wir verzeihen Sie GitHub, dass er das nicht zur Verfügung hat)

Wenn Sie also alle drei oben genannten Situationen kombinieren, erhalten Sie eine Situation, in der nicht zusammengeführte Commits, die zusammengeführt werden, auf der GitHub-Benutzeroberfläche hässlich aussehen.

Ihre Geschichte mit gequetschten Commits wird ungefähr so ​​aussehen

1256556316... Merge pull request #423 from jrandom/add-slideshows
7hgf8978g9... Added new slideshow feature
56556316ad... Merge pull request #324 from ahacker/fix-Android-display
787g8fgf78... Hotfix for Android display issue
f56556316e... Merge pull request #28 from somwhere/select-lang-popup
9080gf6567... Implemented pop-up to select language

Während ohne gequetschte Commits die Geschichte ungefähr so ​​aussehen wird

1256556316... Merge pull request #423 from jrandom/add-slideshows
7hgf8978g9... Added new slideshow feature, JIRA # 848394839
85493g2458... Fixed slideshow display issue in ie
gh354354gh... wip, done for the week
789fdfffdf... minor alignment issue
56556316ad... Merge pull request #324 from ahacker/fix-Android-display
787g8fgf78... hotfix for #5849564648
f56556316e... Merge pull request #28 from somwhere/select-lang-popup
9080gf6567... implemented feature # 65896859
gh34839843... minor fix (typo) for 3rd test

Wenn Sie viele Commits in einer PR-Ablaufverfolgung haben, bei der eine Änderung eingetreten ist, kann dies zu einem Albtraum werden wenn Sie sich auf die Verwendung der GitHub-Benutzeroberfläche beschränken.

Sie finden beispielsweise einen Nullzeiger, der irgendwo in einer Datei de-referenziert wird. Sie sagen also "Wer hat das getan und wann? Welche Release-Versionen sind betroffen?". Dann gehen Sie zur Schuldansicht in der GitHub-Benutzeroberfläche und sehen, dass die Zeile in 789fdfffdf Geändert wurde ... "Oh, aber warten Sie eine Sekunde, diese Zeile wurde nur so eingerückt, dass sie in die Zeile passt Rest des Codes ", also müssen Sie jetzt zum Baumstatus für diese Datei im übergeordneten Commit navigieren und die Schuldseite erneut besuchen ... schließlich finden Sie das Commit ... es ist ein Commit von vor 6 Monaten. "oh **** das könnte Benutzer für 6 Monate betreffen", sagst du ... ah, aber warte, dieses Commit war tatsächlich in einer Pull-Anfrage und wurde erst gestern zusammengeführt und noch hat niemand eine Veröffentlichung gekürzt ... "Verdammt Sie Leute für das Zusammenführen von Commits, ohne den Verlauf zu quetschen "ist der Schrei, der normalerweise nach etwa 2 oder 3 Code-Archäologie-Expeditionen über die GitHub-Benutzeroberfläche zu hören ist

Lassen Sie uns nun überlegen, wie dies funktioniert, wenn Sie die Git-Befehlszeile verwenden (und super-awesome 2.6.2, das das Update für git blame --first-parent Enthält).

  • Wenn Sie die Git-Befehlszeile verwenden, können Sie die Merge-Commit-Nachricht vollständig steuern, sodass das Merge-Commit eine schöne Zusammenfassungszeile haben kann.

So würde unsere Commit-Historie aussehen

$ git log
1256556316... #423 Added new slideshow feature
7hgf8978g9... Added new slideshow feature, JIRA # 848394839
85493g2458... Fixed slideshow display issue in ie
gh354354gh... wip, done for the week
789fdfffdf... minor alignment issue
56556316ad... #324 Hotfix for Android display issue
787g8fgf78... hotfix for #5849564648
f56556316e... #28 Implemented pop-up to select language
9080gf6567... implemented feature # 65896859
gh34839843... minor fix (typo) for 3rd test

Das können wir aber auch

$ git log --first-parent
1256556316... #423 Added new slideshow feature
56556316ad... #324 Hotfix for Android display issue
f56556316e... #28 Implemented pop-up to select language

(Mit anderen Worten: Mit der Git-CLI können Sie Ihren Kuchen auch essen.)

Wenn wir jetzt auf das Nullzeigerproblem stoßen ... nun, wir verwenden einfach git blame --first-parent -w dodgy-file.c Und erhalten sofort das genaue Commit, bei dem die Nullzeiger-De-Referenz in den Hauptzweig eingeführt wurde, wobei einfache Leerzeichenänderungen ignoriert wurden.

Wenn Sie Zusammenführungen über die GitHub-Benutzeroberfläche durchführen, ist git log --first-parent Natürlich sehr beschissen, da GitHub die erste Zeile der Merge-Commit-Nachricht erzwingt:

1256556316... Merge pull request #423 from jrandom/add-slideshows
56556316ad... Merge pull request #324 from ahacker/fix-Android-display
f56556316e... Merge pull request #28 from somwhere/select-lang-popup

Um es kurz zu machen:

Die GitHub-Benutzeroberfläche (Oktober 2015) weist eine Reihe von Mängeln auf, wie Pull-Anforderungen zusammengeführt werden, wie der Commit-Verlauf dargestellt wird und wie Schuldinformationen zugeordnet werden. Der derzeit beste Weg, um diese Fehler in der GitHub-Benutzeroberfläche zu umgehen, besteht darin, die Benutzer aufzufordern, ihre Commits vor dem Zusammenführen zu quetschen.

Die Git-CLI weist diese Probleme nicht auf, und Sie können leicht auswählen, welche Ansicht Sie anzeigen möchten, damit Sie sowohl den Grund ermitteln können, warum eine bestimmte Änderung auf diese Weise vorgenommen wurde (indem Sie sich den Verlauf der nicht aufgelösten Commits ansehen) als auch sehen Sie die effektiv gequetschten Commits.

Post-Skript

Der letzte Grund, der häufig für das Squashing von Commits genannt wird, besteht darin, das Backporting zu vereinfachen. Wenn Sie nur ein Commit für den Backport haben (d. H. Das Squashed Commit), ist es einfach, die Auswahl zu treffen.

Wenn Sie sich die Git-Historie mit git log --first-parent Anschauen, können Sie einfach die Merge-Commits auswählen. Die meisten Leute sind verwirrt, weil Sie die Option -m N Angeben müssen aber Wenn Sie das Commit von git log --first-parent Erhalten haben, wissen Sie, dass es das erste übergeordnete Element ist dass du folgen willst, damit es git cherry-pick -m 1 ... ist.

24

Ich stimme den Ansichten zu, die in anderen Antworten in diesem Thread zum Ausdruck gebracht wurden, dass eine klare und präzise Historie der hinzugefügten Funktionen und behobenen Fehler angezeigt wird. Ich wollte jedoch einen anderen Aspekt ansprechen, dem Ihre Frage entgangen ist, der jedoch nicht ausdrücklich erwähnt wurde. Ein Teil des Problems, das Sie möglicherweise bei einigen Arbeitsmethoden von git haben, besteht darin, dass Sie mit git den Verlauf neu schreiben können, was seltsam erscheint, wenn Sie in git eingeführt werden, nachdem Sie andere Formen der Quellcodeverwaltung verwendet haben, bei denen solche Aktionen nicht möglich sind. Darüber hinaus verstößt dies auch gegen das allgemein anerkannte Prinzip der Quellcodeverwaltung, dass Sie, sobald etwas für die Quellcodeverwaltung festgeschrieben/eingecheckt wurde, in den Status zurückkehren sollten, unabhängig davon, welche Änderungen Sie nach diesem Festschreiben vornehmen. Wie Sie in Ihrer Frage andeuten, ist dies eine dieser Situationen. Ich denke, Git ist ein großartiges Versionskontrollsystem. Um dies zu verstehen, müssen Sie jedoch einige der dahinter stehenden Implementierungsdetails und Entwurfsentscheidungen verstehen. Infolgedessen weist es eine steilere Lernkurve auf. Denken Sie daran, dass git ein verteiltes Versionskontrollsystem sein sollte. Dies erklärt, warum die Designer zulassen, dass der Git-Verlauf neu geschrieben wird, wobei Squash-Commits ein Beispiel dafür sind.

2
Fred Thomsen

Ich würde sehen, ob der Code veröffentlicht wird oder nicht.

Wenn Projekte privat bleiben:

Ich würde empfehlen, nicht zu quetschen und die Herstellung der Wurst zu sehen. Wenn Sie gute und kleine Commits verwenden, sind Tools wie git bisect sehr praktisch, und die Leute können Regressions-Commits schnell lokalisieren und sehen, warum Sie dies getan haben (aufgrund der Commit-Nachricht).

Wenn Projekte an die Öffentlichkeit gehen:

Squash alles, weil einige Commits Sicherheitslücken enthalten können. Zum Beispiel ein Passwort, das festgeschrieben und wieder entfernt wurde.

1
Vince V.

Aufgrund der Perspektive ... Die beste Vorgehensweise besteht darin, ein einzelnes Commit pro einzelnem <<issue-management-system>> Problem wenn möglich.

Sie könnten so viele Commits in Ihrem eigenen Feature-Zweig/Repo haben, wie Sie möchten, aber es ist Ihre Historie, die für das, was Sie jetzt tun, für IHRE Perspektive relevant ist ... es ist nicht die GESCHICHTE für das gesamte TEAM/PROJEKT oder die Anwendung von deren Perspektive in einigen Monaten beibehalten werden ...

Wenn Sie also eine Fehlerbehebung oder Funktion für ein allgemeines Repo festlegen möchten (dieses Beispiel bezieht sich auf den Entwicklungszweig), können Sie dies wie folgt tun:

wie Sie Ihren Feature-Zweig schnell weiterentwickeln können

    # set your current branch , make a backup of it , caveat minute precision
    curr_branch=$(git rev-parse --abbrev-ref HEAD); git branch "$curr_branch"--$(date "+%Y%m%d_%H%M"); git branch -a | grep $curr_branch | sort -nr

    # squash all your changes at once 
    git reset $(git merge-base develop $curr_branch)

    # check the modified files to add 
    git status

    # add the modified files dir by dir, or file by file or all as shown
    git add --all 

    # check once again 
    git log --format='%h %ai %an %m%m %s'  | less

    # add the single message of your commit for the stuff you did 
    git commit -m "<<MY-ISSUE-ID>>: add my very important feature"

    # check once again 
    git log --format='%h %ai %an %m%m %s'  | less

    # make a backup once again , use seconds precision if you were too fast ... 
    curr_branch=$(git rev-parse --abbrev-ref HEAD); git branch "$curr_branch"--$(date "+%Y%m%d_%H%M"); git branch -a | grep $curr_branch | sort -nr

    # compare the old backup with the new backup , should not have any differences 
    git diff <<old-backup>>..<<new-backup-branch>>


    # you would have to git Push force to your feature branch 
    git Push --force 
1
Yordan Georgiev