766 Stimmen

Hinzufügen einer geänderten Datei zu einem älteren (nicht letzten) Commit in Git

Ich habe in der letzten Stunde einige Dinge geändert und sie Schritt für Schritt übertragen, aber ich habe gerade gemerkt, dass ich vergessen habe, eine geänderte Datei vor einigen Übertragungen hinzuzufügen.

Das Protokoll sieht folgendermaßen aus:

GIT TidyUpRequests u:1 d:0> git log 
commit fc6734b6351f6c36a587dba6dbd9d5efa30c09ce 
Author: David Klein <> 
Date:   Tue Apr 27 09:43:55 2010 +0200

    The Main program now tests both Webservices at once

commit 8a2c6014c2b035e37aebd310a6393a1ecb39f463 
Author: David Klein <>
Date:   Tue Apr 27 09:43:27 2010 +0200

    ISBNDBQueryHandler now uses the XPath functions from XPath.fs too

commit 06a504e277fd98d97eed4dad22dfa5933d81451f 
Author: David Klein <> 
Date:   Tue Apr 27 09:30:34 2010 +0200

    AmazonQueryHandler now uses the XPath Helper functions defined in XPath.fs

commit a0865e28be35a3011d0b6091819ec32922dd2dd8 <--- changed file should go here
Author: David Klein <> 
Date:   Tue Apr 27 09:29:53 2010 +0200

    Factored out some common XPath Operations

Irgendwelche Ideen?

1192voto

Greg Hewgill Punkte 882617

Utilisez git rebase . Konkret:

  1. Utilisez git stash um die Änderungen zu speichern, die Sie hinzufügen möchten.
  2. Utilisez git rebase -i HEAD~10 (oder so viele Übertragungen zurück, wie Sie sehen wollen).
  3. Markieren Sie die betreffende Übertragung ( a0865... ) zum Bearbeiten durch Ändern des Wortes pick am Anfang der Zeile in edit . Löschen Sie die anderen Zeilen nicht, da dies die Übertragungen löschen würde.[^vimnote]
  4. Speichern Sie die Rebase-Datei, und Git kehrt in die Shell zurück und wartet darauf, dass Sie den Commit korrigieren.
  5. Den Vorrat aufstocken mit Hilfe von git stash pop
  6. Fügen Sie Ihre Datei mit git add <file> .
  7. Ändern Sie die Übergabe mit git commit --amend --no-edit .
  8. Machen Sie eine git rebase --continue was den Rest Ihrer Übertragungen mit der neuen überschreiben wird.
  9. Wiederholen Sie den Vorgang ab Schritt 2, wenn Sie mehr als eine Übertragung zur Bearbeitung markiert haben.

[^vimnote]: Wenn Sie die vim dann müssen Sie die Taste Insert Taste zum Bearbeiten, dann Esc und geben Sie ein :wq um die Datei zu speichern, den Editor zu beenden und die Änderungen zu übernehmen. Alternativ können Sie auch einen benutzerfreundlichen Git-Commit-Editor konfigurieren avec git config --global core.editor "nano" .

690voto

Joel Purra Punkte 22337

Um einen alten Commit mit einer kleinen Änderung zu "reparieren", ohne die Commit-Nachricht des alten Commits zu ändern, wo OLDCOMMIT ist etwa so 091b73a :

git add <my fixed files>
git commit --fixup=OLDCOMMIT
git rebase --interactive --autosquash OLDCOMMIT^

Sie können auch Folgendes verwenden git commit --squash=OLDCOMMIT um die alte Commit-Nachricht während des Rebase zu bearbeiten.

Siehe Dokumentation für Git Commit y Git-Rebase . Wie immer, wenn Umschreiben der Git-Geschichte sollten Sie nur Commits korrigieren oder zerquetschen, die Sie noch nicht an andere Personen (einschließlich zufälliger Internetnutzer und Build-Server) weitergegeben haben.


Ausführliche Erklärung

  • git commit --fixup=OLDCOMMIT kopiert die OLDCOMMIT Commit-Nachricht und setzt automatisch ein Präfix fixup! damit sie bei der interaktiven Neuberechnung in die richtige Reihenfolge gebracht werden können. ( --squash=OLDCOMMIT tut dasselbe, setzt aber ein Präfix vor squash! .)
  • git rebase --interactive wird ein Texteditor aufgerufen (der können konfiguriert werden ) zum Bestätigen (oder Bearbeiten) der Befehlssequenz wiederherstellen . Es gibt Informationen für Befehl zum Zurücksetzen Änderungen in der Datei; nur Speichern und Beenden der Herausgeber ( :wq において vim ), um mit der Umbasierung fortzufahren.
  • --autosquash setzt automatisch alle --fixup=OLDCOMMIT Übertragungen in der richtigen Reihenfolge. Beachten Sie, dass --autosquash ist nur gültig, wenn die --interactive Option verwendet wird.
  • El ^ において OLDCOMMIT^ bedeutet, dass es sich um einen Verweis auf den Commit kurz vor OLDCOMMIT . ( OLDCOMMIT^ ist das erste Elternteil von OLDCOMMIT .)

Optionale Automatisierung

Die oben genannten Schritte eignen sich zur Überprüfung und/oder Änderung der Befehlssequenz wiederherstellen aber es ist auch möglich, den interaktiven Rebase-Texteditor zu überspringen/zu automatisieren, indem:

71voto

knittl Punkte 214432

Mit Git 1.7 gibt es eine wirklich einfache Möglichkeit, indem man git rebase :

Ihre Dateien bereitstellen:

git add $files

einen neuen Commit erstellen und die Commit-Nachricht des "defekten" Commits wiederverwenden

git commit -c master~4

vorangestellt fixup! in der Betreffzeile (oder squash! wenn Sie Commit (Nachricht) bearbeiten wollen):

fixup! Factored out some common XPath Operations

verwenden. git rebase -i --autosquash um Ihre Übergabe zu korrigieren

16voto

VonC Punkte 1117238

Sie können versuchen, eine rebase --interactive Sitzung, um Ihre alte Übertragung zu ändern (sofern die Sie nicht bereits gedrückt haben diese Commits in ein anderes Repo).

Manchmal kann die in b.2. behobene Sache nicht an die nicht ganz perfekte Übergabe angepasst werden, die sie behebt, weil dieser Commit tief in einer Patch-Serie vergraben ist .
Genau dafür ist interaktives Rebase da: Verwenden Sie es nach vielen "a "s und "b "s, indem Sie Commits neu anordnen und bearbeiten und mehrere Commits zu einem zusammenfassen.

Beginnen Sie mit der letzten Übertragung, die Sie unverändert beibehalten wollen:

git rebase -i <after-this-commit>

Ein Editor wird mit allen Commits in Ihrem aktuellen Zweig (ohne Merge-Commits), die nach dem angegebenen Commit kommen, gestartet.
Sie können die Commits in dieser Liste nach Herzenslust neu anordnen und sie auch wieder entfernen. Die Liste sieht mehr oder weniger wie folgt aus:

pick deadbee The oneline of this commit
pick fa1afe1 The oneline of the next commit
...

Die einzeiligen Beschreibungen sind nur zu Ihrem Vergnügen; git rebase schaut nicht auf sie, sondern auf die Commit-Namen ("deadbee" und "fa1afe1" in diesem Beispiel), also löschen oder bearbeiten Sie die Namen nicht.

Indem Sie den Befehl "pick" durch den Befehl "edit" ersetzen, können Sie git rebase anweisen, nach dem Anwenden dieses Commits anzuhalten, so dass Sie die Dateien und/oder die Commit-Nachricht bearbeiten, den Commit ändern und mit dem Rebase fortfahren können .

2voto

aljabadi Punkte 343

Hier ist eine Funktion, die @Gregs Antwort implementiert:

function gitamendoldcommit() {
    printf "\n\nPress any key if you have no changes other than those you want to add to $1."
    printf "(You can commit your unwanted changes and undo later.):\n\n"
    read foo
    printf "\n\nChange 'pick' to 'edit' in front of $1 (top one), save, close the editor & press any key..."
    printf "Resolve any possible conflicts, if any. then: git add .; git rebase --continue\n\n"
    git rebase -i $1^

    git stash pop
    git add .
    git commit --amend --no-edit
    git rebase --continue
}

Verwendung: (wobei nur die beabsichtigten Änderungen in der Inszenierung vorgenommen werden) gitamendoldcommit $OLDCOMMIT

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X