492 Stimmen

Bestimmte Übertragung entfernen

Ich habe mit einem Freund an einem Projekt gearbeitet, und er hat eine Reihe von Dateien bearbeitet, die nicht hätten bearbeitet werden dürfen. Irgendwie habe ich seine Arbeit mit meiner verschmolzen, entweder, als ich sie abgerufen habe, oder als ich versucht habe, nur die Dateien herauszusuchen, die ich wollte. Ich habe lange gesucht und herumgespielt, um herauszufinden, wie man die Commits entfernt, die die Änderungen an diesen Dateien enthalten, es scheint eine Entscheidung zwischen revert und rebase zu sein, und es gibt keine eindeutigen Beispiele, und die Dokumentation geht davon aus, dass ich mehr weiß als ich tue.

Hier ist also eine vereinfachte Version der Frage:

Wie entferne ich in dem folgenden Szenario die Übergabe 2?

$ mkdir git_revert_test && cd git_revert_test

$ git init
Initialized empty Git repository in /Users/josh/deleteme/git_revert_test/.git/

$ echo "line 1" > myfile

$ git add -A

$ git commit -m "commit 1"
[master (root-commit) 8230fa3] commit 1
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 myfile

$ echo "line 2" >> myfile

$ git commit -am "commit 2"
[master 342f9bb] commit 2
 1 files changed, 1 insertions(+), 0 deletions(-)

$ echo "line 3" >> myfile

$ git commit -am "commit 3"
[master 1bcb872] commit 3
 1 files changed, 1 insertions(+), 0 deletions(-)

Das erwartete Ergebnis ist

$ cat myfile
line 1
line 3

Hier ist ein Beispiel dafür, wie ich versucht habe, umzukehren

$ git revert 342f9bb
Automatic revert failed.  After resolving the conflicts,
mark the corrected paths with 'git add <paths>' or 'git rm <paths>'
and commit the result.

490voto

gaborous Punkte 14077

Es gibt vier Möglichkeiten, dies zu tun:

  • Sauberer Weg, Rückgängigmachung, aber halten Sie im Protokoll der Rückgängigmachung:

    git revert --strategy resolve <commit>
  • Auf die harte Tour, nur die letzte Übertragung ganz entfernen:

    git reset --soft "HEAD^"

Hinweis: Vermeiden Sie git reset --hard da es auch alle Änderungen in Dateien seit der letzten Übertragung verwirft. Wenn --soft nicht funktioniert, versuchen Sie stattdessen --mixed ou --keep .

  • Rebase (zeigt das Protokoll der letzten 5 Commits an und löscht die Zeilen, die Sie nicht wollen, oder ordnet sie neu an, oder zerdrückt mehrere Commits in einem, oder macht alles andere, was Sie wollen, dies ist ein sehr vielseitiges Werkzeug):

    git rebase -i HEAD~5

Und wenn ein Fehler gemacht wird:

git rebase --abort
  • Quick rebase: entfernt nur einen bestimmten Commit anhand seiner id:

    git rebase --onto commit-id^ commit-id
  • Alternativen: Sie können es auch versuchen:

    git cherry-pick commit-id
  • Eine weitere Alternative:

    git revert --no-commit
  • Als letzten Ausweg, wenn Sie volle Freiheit bei der Bearbeitung der Historie benötigen (z.B. weil Git Ihnen nicht erlaubt, das zu bearbeiten, was Sie wollen), können Sie folgendes verwenden sehr schnell Open-Source-Anwendung: reposurgeon .

Hinweis: Natürlich werden alle diese Änderungen lokal vorgenommen, Sie sollten git push um die Änderungen auf der Fernbedienung zu übernehmen. Und für den Fall, dass Ihr Projektarchiv den Commit nicht entfernen will ("no fast-forward allowed", was passiert, wenn Sie einen Commit entfernen wollen, den Sie bereits gepusht haben), können Sie git push -f um die Änderungen zu erzwingen.

Hinweis2: Wenn Sie an einem Zweig arbeiten und einen Push erzwingen müssen, sollten Sie unbedingt vermeiden git push --force weil dadurch andere Zweige überschrieben werden können (wenn Sie dort Änderungen vorgenommen haben, selbst wenn sich Ihr aktueller Checkout in einem anderen Zweig befindet). Bevorzugen Sie immer den entfernten Zweig angeben, wenn Sie Push erzwingen : git push --force origin your_branch .

298voto

JD-V Punkte 2576

Hier ist eine einfache Lösung:

git rebase -i HEAD~x

(Anmerkung: x ist die Anzahl der Übertragungen)

Beim Ausführen wird eine Notepad-Datei geöffnet. Geben Sie ein. drop neben Ihrem Commit.
Wenn Sie Vim nicht kennen, klicken Sie einfach auf jede Wortwahl, die Sie bearbeiten möchten, und drücken Sie dann die Taste "I" (für den Einfügemodus). Sobald Sie mit dem Tippen fertig sind, drücken Sie die "esc"-Taste, um den Einfügemodus zu verlassen.

enter image description here

und das war's, Sie sind fertig... Synchronisieren Sie einfach das Git-Dashboard und die Änderungen werden an das Remote-System übertragen.

Wenn der Commit, den Sie ablegen, bereits auf der Remote vorhanden war, müssen Sie den Push erzwingen. Da --force als schädlich verwenden git push --force-with-lease .

86voto

Hal Eisen Punkte 890

Der Algorithmus, den Git bei der Berechnung der zu revertierenden Diffs verwendet, erfordert, dass

  1. Die Zeilen, die rückgängig gemacht werden, werden durch spätere Übertragungen nicht verändert.
  2. Später in der Geschichte wird es keine weiteren "benachbarten" Verpflichtungen geben.

Die Definition von "benachbart" basiert auf der Standardanzahl von Zeilen eines Kontextdiffs, die 3 beträgt. Wenn also "myfile" wie folgt konstruiert wurde:

$ cat >myfile <<EOF
line 1
junk
junk
junk
junk
line 2
junk
junk
junk
junk
line 3
EOF
$ git add myfile
$ git commit -m "initial check-in"
 1 files changed, 11 insertions(+), 0 deletions(-)
 create mode 100644 myfile

$ perl -p -i -e 's/line 2/this is the second line/;' myfile
$ git commit -am "changed line 2 to second line"
[master d6cbb19] changed line 2
 1 files changed, 1 insertions(+), 1 deletions(-)

$ perl -p -i -e 's/line 3/this is the third line/;' myfile
$ git commit -am "changed line 3 to third line"
[master dd054fe] changed line 3
 1 files changed, 1 insertions(+), 1 deletions(-)

$ git revert d6cbb19
Finished one revert.
[master 2db5c47] Revert "changed line 2"
 1 files changed, 1 insertions(+), 1 deletions(-)

Dann funktioniert alles wie erwartet.

Die zweite Antwort war sehr interessant. Es gibt eine Funktion, die noch nicht offiziell veröffentlicht wurde (obwohl sie in Git v1.7.2-rc2 verfügbar ist), namens Revert Strategy. Sie können Git wie folgt aufrufen:

mit einem Git rückgängig machen --Strategie beschließen <Bitte>

und es sollte besser herausfinden, was Sie gemeint haben. Ich weiß nicht, wie die Liste der verfügbaren Strategien aussieht, und ich kenne auch nicht die Definition einer Strategie.

69voto

tk_ Punkte 14471

Ansatz 1

Holen Sie sich zuerst den Commit-Hash (z.B. 1406cd61), den Sie rückgängig machen müssen. Eine einfache Lösung ist der folgende Befehl,

$ git revert 1406cd61

wenn Sie nach 1406cd61 commit weitere Änderungen an 1406cd61 Dateien vorgenommen haben, funktioniert obiger einfacher Befehl nicht. Dann müssen Sie die folgenden Schritte tun, die Rosinenpickerei ist.

Ansatz 2

Bitte folgen Sie der nachstehenden Abfolge von Aktionen. Da wir --force verwenden, müssen Sie über Adminrechte über das Git-Repositorium, um dies zu tun.

Schritt 1: Suchen Sie den Commit vor dem Commit, den Sie entfernen möchten git log

Schritt 2: Überprüfen Sie diese Übertragung git checkout <commit hash>

Schritt 3: Erstellen Sie einen neuen Zweig unter Verwendung Ihrer aktuellen Checkout-Übertragung git checkout -b <new branch>

Schritt 4: Jetzt müssen Sie den Commit nach dem entfernten Commit hinzufügen git cherry-pick <commit hash>

Schritt 5: Wiederholen Sie nun Schritt 4 für alle anderen Commits, die Sie behalten möchten.

Schritt 6: Sobald alle Übertragungen zu Ihrem neuen Zweig hinzugefügt und übertragen wurden. Überprüfen Sie, ob sich alles im richtigen Zustand befindet und wie vorgesehen funktioniert. Überprüfen Sie noch einmal, ob alles übertragen wurde: git status

Schritt 7: Wechseln Sie zu Ihrem gebrochenen Zweig git checkout <broken branch>

Schritt 8: Führen Sie nun einen Hard-Reset auf dem kaputten Zweig zu der Übergabe durch, die vor derjenigen liegt, die Sie entfernen möchten git reset --hard <commit hash>

Schritt 9: Führen Sie Ihren festen Zweig in diesen Zweig ein git merge <branch name>

Schritt 10: Schieben Sie die zusammengeführten Änderungen zurück zum Ursprung. WARNUNG: Dadurch wird das entfernte Projektarchiv überschrieben! git push --force origin <branch name>

Sie können den Vorgang auch durchführen, ohne einen neuen Zweig zu erstellen, indem Sie Schritt 2 und 3 durch Schritt 8 ersetzen und Schritt 7 und 9 nicht ausführen.

42voto

Andrew Walker Punkte 2401

Sie haben die Wahl zwischen

  1. Beibehaltung des Fehlers und Einführung einer Korrektur und
  2. Beseitigung des Fehlers und Änderung des Verlaufs.

Sie sollten wählen, (1) ob die fehlerhafte Änderung von jemand anderem aufgegriffen wurde und (2) ob der Fehler auf einen privaten, nicht gepushten Zweig beschränkt ist.

Git revert ist ein automatisiertes Werkzeug für (1), es erstellt einen neuen Commit und macht einen früheren Commit rückgängig. Sie werden den Fehler und die Entfernung in der Projekthistorie sehen, aber Leute, die von Ihrem Repository ziehen, werden keine Probleme haben, wenn sie aktualisieren. In Ihrem Beispiel funktioniert es nicht automatisch, also müssen Sie 'myfile' bearbeiten (um Zeile 2 zu entfernen) und git add myfilegit commit um den Konflikt zu bewältigen. Sie werden dann vier Commits in Ihrer Historie haben, wobei Commit 4 den Commit 2 rückgängig macht.

Wenn es niemanden interessiert, dass sich Ihre Geschichte ändert, können Sie sie umschreiben und Commit 2 entfernen (Wahl 2). Der einfachste Weg dies zu tun ist die Verwendung von git rebase -i 8230fa3 . Dies führt Sie in einen Editor und Sie können den fehlerhaften Commit nicht einbeziehen, indem Sie den Commit entfernen (und "pick" neben den anderen Commit-Meldungen lassen). Informieren Sie sich über die Konsequenzen dieser Vorgehensweise .

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