Frage Wie ändere ich ein spezifiziertes Commit in git?


Ich übermittle in der Regel eine Liste der Commits zur Überprüfung. Wenn ich habe:

  • HEAD 
  • Commit3 
  • Commit2 
  • Commit1

Ich weiß, dass ich Head Commit mit modifizieren kann git commit --amend, aber wie kann ich modifizieren? Commit1, da es nicht das ist HEAD verpflichten?


1700
2017-07-27 05:19


Ursprung


Antworten:


Sie können z. B. git rebase verwenden, wenn Sie zurück zum Commit modifizieren möchten bbc643cd, Lauf

$ git rebase --interactive 'bbc643cd^'

Ändern Sie im Standardeditor pick zu edit in der Zeile, deren Commit Sie ändern möchten. Nehmen Sie Ihre Änderungen vor und binden Sie sie dann mit der gleichen Nachricht wie zuvor ein:

$ git commit --all --amend --no-edit

um das Commit zu ändern und danach

$ git rebase --continue

um zum vorherigen Head Commit zurückzukehren.

WARNUNG: Beachten Sie, dass dies die SHA-1 dieses Commits ändert sowie alle Kinder Mit anderen Worten, das schreibt die Geschichte von diesem Punkt an neu. Sie können damit Repos brechen wenn Sie mit dem Befehl drücken git push --force


2232
2017-07-27 05:28



Benutze die tolle interaktive Rebase:

git rebase -i @~9   # Show the last 9 commits in a text editor

Finden Sie den gewünschten Commit, ändern Sie pick zu e (edit), und speichern und schließen Sie die Datei. Git wird zu diesem Commit zurückspulen und Ihnen entweder erlauben:

  • benutzen git commit --amend um Änderungen vorzunehmen, oder
  • benutzen git reset @~ das letzte Commit zu verwerfen, aber nicht die Änderungen an den Dateien (d. h. Sie bringen Sie zu dem Punkt, an dem Sie waren, als Sie die Dateien bearbeitet, aber noch nicht festgelegt hatten).

Letzteres ist nützlich für komplexere Dinge wie das Teilen in mehrere Commits.

Dann renne git rebase --continue, und Git wiederholt die nachfolgenden Änderungen zusätzlich zu Ihrem geänderten Commit. Sie werden möglicherweise aufgefordert, einige Zusammenführungskonflikte zu beheben.

Hinweis: @ ist Kurzschrift für HEAD, und ~ ist das Commit vor dem angegebenen Commit.

Lesen Sie mehr über Geschichte umschreiben in der Git-Dokumentation.


Haben Sie keine Angst zu Rebase

ProTip: Haben Sie keine Angst, mit "gefährlichen" Befehlen zu experimentieren, die den Verlauf neu schreiben * - Git löscht Ihre Commits nicht standardmäßig für 90 Tage; Sie können sie im Reflog finden:

$ git reset @~3   # go back 3 commits
$ git reflog
c4f708b HEAD@{0}: reset: moving to @~3
2c52489 HEAD@{1}: commit: more changes
4a5246d HEAD@{2}: commit: make important changes
e8571e4 HEAD@{3}: commit: make some changes
... earlier commits ...
$ git reset 2c52489
... and you're back where you started

* Achten Sie auf Optionen wie --hard und --force obwohl - sie können Daten verwerfen.
* Außerdem sollten Sie den Verlauf in den Zweigen, an denen Sie zusammenarbeiten, nicht neu schreiben.



Auf vielen Systemen git rebase -i wird Vim standardmäßig öffnen. Vim funktioniert nicht wie die meisten modernen Texteditoren. Schauen Sie sich das an wie man mit Vim umbasiert. Wenn Sie lieber einen anderen Editor verwenden möchten, ändern Sie ihn mit git config --global core.editor your-favorite-text-editor.


304
2018-04-29 17:50



Interaktiv Rebase mit --autosquash ist etwas, das ich häufig benutze, wenn ich frühere Commits tiefer in der Geschichte beheben muss. Es beschleunigt wesentlich den Prozess, den ZelluX's Antwort veranschaulicht, und ist besonders praktisch, wenn Sie mehr als einen Commit haben, den Sie bearbeiten müssen.

Aus der Dokumentation:

--autosquash

Wenn die Commit-Log-Nachricht mit "squash! ..." beginnt (oder "fixup! ..."), und es eine Commit gibt, deren Titel mit der gleichen beginnt ..., modifiziere automatisch die todo-Liste von rebase -i, so dass die commit markiert für Squashing kommt direkt nach dem Commit geändert werden

Angenommen, Sie haben eine Historie, die wie folgt aussieht:

$ git log --graph --oneline
* b42d293 Commit3
* e8adec4 Commit2
* faaf19f Commit1

und Sie haben Änderungen, die Sie an Commit2 ändern möchten, und übernehmen dann Ihre Änderungen mit

$ git commit -m "fixup! Commit2"

Alternativ können Sie den Commit-sha anstelle der Commit-Nachricht verwenden, also "fixup! e8adec4 oder auch nur ein Präfix der Commit-Nachricht.

Dann initiieren Sie eine interaktive Rebase für das Commit vor

$ git rebase e8adec4^ -i --autosquash

Ihr Editor öffnet sich mit den bereits korrekt bestellten Commits

pick e8adec4 Commit2
fixup 54e1a99 fixup! Commit2
pick b42d293 Commit3

Alles, was Sie tun müssen, ist speichern und beenden


57
2017-09-29 17:59



Lauf:

$ git rebase --interactive commit_hash^

jeder ^ Gibt an, wie viele Commits Sie bearbeiten möchten. Wenn es nur einen gibt (den angegebenen Commit-Hash), fügen Sie einfach einen hinzu ^.

Mit Vim ändern Sie die Wörter pick zu reword für die Commits, die Sie ändern, speichern und beenden möchten (:wq). Dann wird git Sie mit jedem Commit, das Sie als reword markiert haben, auffordern, damit Sie die Commit-Nachricht ändern können.

Jede Commit-Nachricht, die Sie speichern und beenden müssen (:wq) um zur nächsten Commit-Nachricht zu gehen

Wenn Sie beenden möchten, ohne die Änderungen zu übernehmen, drücken Sie :q!

BEARBEITEN: um darin zu navigieren vim Sie nutzen j hinaufgehen, k nach unten gehen, h nach links gehen, und l nach rechts gehen (all dies in NORMAL Modus, drücken Sie ESC zu gehen NORMAL Modus). Um einen Text zu bearbeiten, drücken Sie i damit du die INSERT Modus, wo Sie Text einfügen. Drücken Sie ESC zurückgehen zu NORMAL Modus :)

AKTUALISIEREN: Hier ist ein guter Link von github Listing Wie man (fast) alles mit git rückgängig macht 


30
2017-07-02 19:11



Wenn Sie aus irgendeinem Grund interaktive Editoren nicht mögen, können Sie verwenden git rebase --onto.

Angenommen, Sie möchten Änderungen vornehmen Commit1. Zuerst verzweigen Sie von Vor  Commit1:

git checkout -b amending [commit before Commit1]

Zweitens, schnappen Commit1 mit cherry-pick:

git cherry-pick Commit1

Jetzt ändern Sie Ihre Änderungen und erstellen Commit1':

git add ...
git commit --amend -m "new message for Commit1"

Und schließlich, nachdem du irgendwelche anderen Änderungen gespeichert hast, verpasse den Rest deiner Commits bis zu master oben auf deinem neues Festschreiben:

git rebase --onto amending Commit1 master

Lesen Sie: "Rebase, auf den Zweig amending, alle Commits zwischen Commit1 (nicht inklusive) und master (inklusive). "Das heißt, Commit2 und Commit3, wobei das alte Commit1 komplett weggelassen wird. Sie könnten sie einfach per Mausklick auswählen, aber dieser Weg ist einfacher.

Denken Sie daran, Ihre Zweige zu säubern!

git branch -d amending

12
2017-10-22 12:19



Kam zu diesem Ansatz (und es ist wahrscheinlich genau das gleiche wie mit interaktiven Rebase), aber für mich ist es ziemlich einfach.

Hinweis: Ich stelle diesen Ansatz zur Veranschaulichung dessen vor, was Sie tun können, anstatt eine alltägliche Alternative zu sein. Da es viele Schritte (und möglicherweise einige Vorbehalte) hat.

Angenommen, Sie möchten das Commit ändern 0 und du bist gerade dabei feature-branch

some-commit---0---1---2---(feature-branch)HEAD

Checkout zu diesem Commit und erstellen Sie ein quick-branch. Sie können Ihren Feature-Zweig auch als Wiederherstellungspunkt klonen (vor dem Start).

?(git checkout -b feature-branch-backup)
git checkout 0
git checkout -b quick-branch

Sie werden jetzt so etwas haben:

0(quick-branch)HEAD---1---2---(feature-branch)

Bühnenwechsel, alles andere verstauen.

git add ./example.txt
git stash

Änderungen bestätigen und zurück zur Kasse gehen feature-branch

git commit --amend
git checkout feature-branch

Sie werden jetzt so etwas haben:

some-commit---0---1---2---(feature-branch)HEAD
           \
             ---0'(quick-branch)

Rebase feature-branch auf zu quick-branch (Lösen Sie alle Konflikte auf dem Weg). Verstauen und entfernen quick-branch.

git rebase quick-branch
git stash pop
git branch -D quick-branch

Und du hast am Ende:

some-commit---0'---1'---2'---HEAD(feature-branch)

Git wird nicht duplizieren (obwohl ich nicht wirklich sagen kann, in welchem ​​Umfang), die 0 beim Rebasieren eingeht.

Hinweis: Alle Commit-Hashes werden geändert, beginnend mit dem Commit, das ursprünglich geändert werden sollte.


6
2018-06-01 11:57



Um einen nicht interaktiven Befehl zu erhalten, lege ein Skript mit diesem Inhalt in deinen PFAD:

#!/bin/sh
#
# git-fixup
# Use staged changes to modify a specified commit
set -e
cmt=$(git rev-parse $1)
git commit --fixup="$cmt"
GIT_EDITOR=true git rebase -i --autosquash "$cmt~1"

Verwenden Sie es, indem Sie Ihre Änderungen (mit git add) und dann rennen git fixup <commit-to-modify>. Natürlich ist es immer noch interaktiv, wenn Sie Konflikte bekommen.


4
2018-01-16 15:27



Vollständig nicht interaktiver Befehl(1)

Ich dachte nur, ich würde einen Alias ​​teilen, den ich dafür verwende. Es basiert auf nicht interaktiv interaktive Rebase Um es zu deinem Git hinzuzufügen, führe diesen Befehl aus (Erklärung unten):

git config --global alias.amend-to '!f() { SHA=`git rev-parse "$1"`; git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"; }; f'

Der größte Vorteil dieses Befehls ist die Tatsache, dass es ist Nein-Vim.


(1)da es natürlich während der Rebase keine Konflikte gibt

Verwendung

git amend-to <REV> # e.g.
git amend-to HEAD~1
git amend-to aaaa1111

Der Name amend-to scheint angemessen IMHO. Vergleichen Sie den Fluss mit --amend:

git add . && git commit --amend --no-edit
# vs
git add . && git amend-to <REV>

Erläuterung

  • git config --global alias.<NAME> '!<COMMAND>' - Erzeugt einen globalen Git Alias ​​namens <NAME> Das wird non-Git-Befehl ausführen <COMMAND>
  • f() { <BODY> }; f - eine "anonyme" Bash-Funktion.
  • SHA=`git rev-parse "$1"`; - Konvertiert das Argument in git revision und weist das Ergebnis der Variablen zu SHA
  • git commit --fixup "$SHA" - fixup-commit für SHA. Sehen git-commit Dokumente
  • GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"
    • git rebase --interactive "$SHA^" Teil wurde durch andere Antworten abgedeckt.
    • --autosquash wird in Verbindung mit verwendet git commit --fixup, sehen git-rebase Dokumente Für mehr Information
    • GIT_SEQUENCE_EDITOR=true macht das Ganze nicht interaktiv. Dieser Hack habe ich gelernt von diesem Blogpost.

4
2018-02-27 01:47



Für mich war es für das Entfernen einiger Anmeldeinformationen aus einem Repo. Ich habe versucht, mich zu reversieren und bin in eine Menge scheinbar unzusammenhängender Konflikte auf dem Weg gestolpert, als ich versucht habe, einen Rebase zu machen - weitermachen. Versuchen Sie nicht, sich selbst zu rebasen, verwenden Sie das Tool namens BFG (brew install bfg) auf dem Mac.


1
2017-11-07 07:24



Ich habe das gelöst,

1) durch Erstellen eines neuen Commits mit Änderungen, die ich möchte ..

r8gs4r commit 0

2) Ich weiß, welches Commit ich mit ihm verschmelzen muss. was ist commit 3.

damit, git rebase -i HEAD~4 # 4 steht für den letzten 4-Commit (hier Commit 3 steht auf Platz 4)

3) in der interaktiven Rebase wird das letzte Commit unten liegen. es wird gleich aussehen,

pick q6ade6 commit 3
pick vr43de commit 2
pick ac123d commit 1
pick r8gs4r commit 0

4) Hier müssen wir Commit neu anordnen, wenn Sie mit bestimmten verschmelzen wollen. es sollte so sein,

parent
|_child

pick q6ade6 commit 3
f r8gs4r commit 0
pick vr43de commit 2
pick ac123d commit 1

Nach der Neuanordnung müssen Sie ersetzen p  pick mit f (in Ordnung bringen wird ohne Commit-Nachricht zusammengeführt) oder s (quetschen Zusammenführen mit Commit-Nachricht kann sich in der Laufzeit ändern)

und dann speichere deinen Baum.

Jetzt fusioniere mit bestehendem Commit.

Hinweis: Es ist nicht die bevorzugte Methode, wenn Sie nicht selbstständig sind. ob   Sie haben große Teamgröße, es ist keine akzeptable Methode, Git umzuschreiben   Baum wird in Konflikten enden, die Sie sonst nicht kennen. wenn du willst   um dich mit weniger commits sauber zu halten, kannst du das versuchen und wenn es ist   kleines Team sonst ist es nicht zu bevorzugen .....


1
2018-01-05 18:35



Beyogen auf Dokumentation

Änderung der Nachricht von älteren oder mehreren Commit-Nachrichten

git rebase -i HEAD~3 

Oben sehen Sie eine Liste der letzten 3 Commits für den aktuellen Zweig, ändern Sie 3 zu etwas anderem, wenn Sie mehr wollen. Die Liste sieht etwa so aus:

pick e499d89 Delete CNAME
pick 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.

Ersetzen wählen mit umformulieren vor jeder Commit-Nachricht, die Sie ändern möchten. Nehmen wir an, Sie ändern das zweite Commit in der Liste, Ihre Datei sieht etwa so aus:

pick e499d89 Delete CNAME
reword 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.

Speichern und schließen Sie die Festschreiblistendatei. Dadurch wird ein neuer Editor geöffnet, in dem Sie Ihre Festschreibnachricht ändern, die Festschreibnachricht ändern und speichern können.

Schließlich erzwingen Sie die geänderten Commits.

git push --force

0
2018-05-17 08:38