Fügen Sie mit Magit eine Änderung zu einem vorherigen Commit hinzu

42

Ich habe 2 Commits, A und B, die zum Push bereit sind. Mir ist klar, dass ich vergessen habe, in A etwas hinzuzufügen.

Wie kann ich diese Änderung mit Magit zu A hinzufügen? Ich weiß nicht einmal, welchen Teil der Git-Dokumentation ich mir ansehen soll.

Mathieu Marques
quelle

Antworten:

67

Stellen wir uns für einen Moment vor, Sie möchten dem HEADCommit etwas hinzufügen , dh "das zweite Commit B" in Ihrem Beispiel.

Das Commit-Popup auf centhält ein verbindliches " aAmend". Durch Drücken dieser Taste werden die bereitgestellten Änderungen am Festschreiben "geändert" HEAD. Da Commits in Git nicht veränderbar sind, wird das alte Commit durch ein neues Commit ersetzt. Ein Puffer mit der alten Festschreibungsnachricht wird geöffnet, sodass Sie ihn ändern können, falls die hinzugefügte Änderung auch eine Anpassung der Nachricht erfordert. Drücken C-c C-cSie wie immer, wenn Sie mit dem Bearbeiten der Nachricht fertig sind. Dies entspricht der Ausführung git commit --amendin der Befehlszeile.

  • a Ändern - Fügen Sie die bereitgestellten Änderungen hinzu HEADund bearbeiten Sie die Commit-Nachricht

Da es häufig vorkommt, dass Sie nur die Änderung oder die Meldung anpassen müssen , bietet Magit zwei zusätzliche Varianten an:

  • e Erweitern - Fügen Sie die bereitgestellten Änderungen hinzu, HEADohne die Festschreibungsnachricht zu bearbeiten
  • w Reword - Ändern Sie die Nachricht von, HEADohne die bereitgestellten Änderungen hinzuzufügen

Wenn Sie ein Commit bearbeiten möchten, das nicht vorhanden ist HEAD, funktioniert das oben beschriebene nicht. Diese Befehle "modifizieren" (dh ersetzen) immer das HEADCommit. Git bietet keinen einzigen Befehl zum Ändern eines Commits an, außer HEADdies ist etwas komplizierter.

Magit bietet einen solchen Befehl an, aber da es Situationen gibt, in denen dies in mehreren Schritten vorzuziehen ist, werden wir diesen zuerst erörtern.

Das Ändern eines anderen Commits als HEADkann in drei Schritte unterteilt werden:

  1. Machen Sie vorübergehend das andere commit ( A) HEAD.
  2. Ändern Sie die HEAD(wie oben beschrieben), was zu einem Commit führt A'.
  3. Weisen Sie Git an, die folgenden Commits erneut anzuwenden A, jedoch zusätzlich A'.

Dies kann über eine interaktive Rebase erfolgen. Geben Sie rdas Fütterungsmaterial Popup zu zeigen. Geben Sie dann mden „bearbeiten ein commit“ aufzurufen rebase Variante. Ein Puffer mit den letzten Commits wird angezeigt. Bewegen Sie sich zu dem Commit, das Sie ändern möchten, und geben C-c C-cSie es ein, um es auszuwählen. Git führt dann einen Rücklauf des Verlaufs zu diesem Commit durch und zeigt Informationen über den laufenden Rücklauf im Statuspuffer an.

Ändern Sie HEADwie oben beschrieben. Dann sag Git, dass du fertig bist, indem du tippst r r. Wenn A'und BKonflikt dann rebase hält an , Bund Sie haben , um den Konflikt zu lösen. Nachdem Sie dies getan haben, drücken Sie, r rum fortzufahren.

Wenn Sie wissen, dass Ihre Änderungen zu AKonflikten führen B, gehen Sie wie oben beschrieben vor, andernfalls verwenden Sie den folgenden Ansatz.


Git erlaubt das Erstellen von "Fixup Commits" mit git commit --fixup A. Dadurch wird ein neues Commit erstellt, in dem Änderungen aufgezeichnet werden, die "in einem anderen Commit hätten vorgenommen werden müssen". Dieses Commit wird das Neue HEAD. Es gibt auch eine --squashVariante. Informationen zu den Unterschieden finden Sie auf der git-commitManpage.

Um das AFestschreiben und das neue Festschreiben tatsächlich zu kombinieren A'und dann erneut Bdarauf anzuwenden, müssen Sie rebase verwenden. Magit bietet dazu einen komfortablen Befehl r f.

Der Hauptunterschied zum obigen Ansatz besteht darin, dass wir hier zuerst ein neues Commit erstellen und es dann neu definieren, um es mit dem "Ziel" zu kombinieren und erneut anzuwenden B. Oben haben wir mit dem Umbasieren statt mit dem Festschreiben begonnen.

In Magit sind sowohl die --fixupals auch die --squashVarianten über das Commit-Popup auf fund verfügbar s. Magit bietet aber auch "sofortige" Varianten der Fixup- und Squash-Befehle für Fund an S. Diese Varianten erstellen ein neues Commit wie die "non-instant" -Varianten, kombinieren dann jedoch sofort das Fixup-Commit mit dem Ziel-Commit unter Verwendung von rebase, ohne dass Sie einen anderen Befehl aufrufen müssen.

"Instant fixup" ( c F) ist im Wesentlichen dasselbe wie "extend HEAD" ( c e), außer dass es für jedes Commit funktioniert, nicht nur HEAD.


Weitere Lektüre:

Tarsius
quelle
Kristallklar! Vielen Dank, tolles Paket BTW.
Mathieu Marques
1
Nun, ich denke es gibt einige matschige Teile in der zweiten Hälfte meiner Antwort. Aber um diese zu vermeiden, müsste ich die Länge dieser bereits langen Antwort verdoppeln, daher bin ich froh, dass dies für Sie funktioniert
;-)
Danke für diese Antwort tarsius, das funktioniert wirklich bei mir.
Anquegi
Die Klarheit der ersten Hälfte dieser Erklärung macht das Lesen der zweiten Hälfte, die viel schwieriger zu verfolgen ist, ziemlich frustrierend!
Lyn Headley
git-commitManpage-Weiterleitungen mit git-rebase(1)den folgenden Zeilen: Die vorgeschlagene Festschreibungsnachricht für die gefaltete Festschreibung ist die Verkettung der Festschreibungsnachrichten der ersten Festschreibung und derjenigen mit dem Befehl "squash", lässt jedoch die Festschreibungsnachrichten der Festschreibungen mit dem Befehl "fixup" aus. Befehl. IOW, verwenden Sie fixup, wenn Sie nur den Code im vorherigen Commit korrigieren möchten, und squash, wenn Sie auch die Commit-Nachricht korrigieren möchten .
Yasushi Shoji
3

git commit --amend –C HEADist der Git-Befehl, nach dem Sie suchen möchten, und mit dem Sie in Magit Änderungen vornehmen können C-c C-a.

Ryan
quelle
Ich benutze Magit aktuell, C-c C-astammt aus einer älteren Version (glaube ich). Außerdem sehe ich keine Spur von "Nachbesserung" im Hilfepuffer ( ?).
Mathieu Marques
Siehe Rémis Antwort für das Äquivalent von magit 2.x.
Npostavs
3

Ein Workflow ist also:

  • Mach dein Wechselgeld
  • c (Festschreiben) f (Fixup - Wählen Sie "Festschreiben")

Dann

  • r (rebase) -a (Autosquash, kann voreingestellt werden) i (interaktiv)

Das automatische Quetschen verschiebt alle! Fixup-Commits automatisch an die richtige Stelle und legt fest, dass sie auf der Basisstation gequetscht werden.

Stsquad
quelle
Das einzige, was ich getan habe, was Sie nicht gesagt haben, war, zwischen Ihrer ersten und der zweiten Kugel zu inszenieren. Schlagen iergibt mich Cannot rebase: Your index contains uncommitted changes. Please commit or stash them.. Es sei denn, ich habe keine nicht festgeschriebenen Änderungen. : /
Mathieu Marques
Versuchte es noch einmal nach dem Ziehen, Proceed despite merge in rebase range? [c]ontinue, [s]elect other, [a]bort. Versucht es, mir zu sagen, dass mein Fixup bei der bevorstehenden Fusion scheitern könnte?
Mathieu Marques
@MathieuMarques: "Außer ich habe keine nicht festgeschriebenen Änderungen" - git denkt, dass Sie das tun. Beachten Sie, dass in der Nachricht Änderungen vorgeschlagen werden, die nicht nicht in der Phase enthalten sind. Betreff: merge in rebasesiehe BUGS unter git help rebase. Ich schlage vor, das Update vor dem Upstream zu machen.
Npostavs
1

Für die Änderung des letzten Commits ist es "c a". Fixup ist für die Korrektur älterer Commits gedacht.

Rémi
quelle
In diesem Fall habe ich A und dann B festgelegt. Der Übersichtlichkeit halber wurde der Beitrag aktualisiert.
Mathieu Marques