Entfernen Sie ein bestimmtes Commit

287

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 in meine integriert, entweder als ich sie gezogen habe oder als ich versucht habe, nur die gewünschten Dateien auszuwählen. Ich habe lange gesucht und gespielt und versucht herauszufinden, wie die Commits entfernt werden können, die die Änderungen an diesen Dateien enthalten. Es scheint ein Fehler zwischen Zurücksetzen und Wiederherstellen zu sein, und es gibt keine einfachen Beispiele Die Ärzte gehen davon aus, dass ich mehr weiß als ich.

Hier ist eine vereinfachte Version der Frage:

Wie entferne ich in dem folgenden Szenario Commit 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, zurückzukehren

$ 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.
Joshua Cheek
quelle
4
Wenn jemand dies bei der Suche nach demselben Problem findet, habe ich Folgendes getan: Kopieren und Einfügen. Ernsthaft. Verbrachte mehr als 6 Stunden damit, die vorgeschlagenen Lösungen zum Laufen zu bringen, ohne Erfolg. Am Ende hatte ich keine Zeit mehr, zog das Original hoch und kopierte / fügte nur etwa 20 Dateien ein. Es dauerte weniger als 5 Minuten, und seitdem ist alles in Ordnung (selbst wenn diese Dateien mit Änderungen in anderen Zweigen zusammengeführt werden, die vor diesem Fiasko stattgefunden haben). Ich schlage vor, Sie gehen auch so vor. Es ist nicht nur das einfachste, ich vermute auch, dass es das einzige ist, was funktioniert.
Joshua Cheek
Ich hatte ein ähnliches Problem, aber vielleicht ein komplexeres: Ich hatte einen Zweig mit Hunderten von Commits, die ich zerquetschen wollte. Leider wurden Commits von einem anderen Zweig an einem Zwischenpunkt wieder in den Zweig eingefügt, sodass ein "Auflösen" erforderlich war, bevor ich quetschen konnte. Ich bin einen ähnlichen Weg gegangen, wie von tk unten vorgeschlagen (Kirschernte + unter Verwendung der Bereichsnotation), aber es hat Konflikte in einigen anderen Dateien erzeugt. Am Ende war Copy & Paste + ein paar manuelle Änderungen der einfachste und vorhersehbarste Weg vorwärts. Auf jeden Fall eine Überlegung wert, wenn Sie zu viel Zeit damit verbringen.
Federico

Antworten:

73

Der Algorithmus, den Git bei der Berechnung der zurückzusetzenden Diffs verwendet, erfordert dies

  1. Die zurückgesetzten Zeilen werden durch spätere Festschreibungen nicht geändert.
  2. dass es später in der Geschichte keine anderen "benachbarten" Commits gibt.

Die Definition von "benachbart" basiert auf der Standardanzahl von Zeilen aus einem Kontextdifferenz, die 3 ist. 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 namens Revert Strategy, die noch nicht offiziell veröffentlicht wurde (obwohl sie in Git v1.7.2-rc2 verfügbar ist). Sie können git wie folgt aufrufen:

git revert - strategie auflösen <commit>

und es sollte einen besseren Job machen, um herauszufinden, was Sie meinten. Ich weiß weder die Liste der verfügbaren Strategien noch die Definition einer Strategie.

Hal Eisen
quelle
1
perl -pist nützlich , um die Schleife und sehr kurz (eine Zeile) Schreiben von Programmen übergeben ihre Eingabe an den Ausgang, ähnlich wie Sed. perl -iist für die Bearbeitung von Dateien verwendet anstelle . perl -eSo senden Sie den auszuwertenden Code .
Hal Eisen
281

Es gibt vier Möglichkeiten, dies zu tun:

  • Sauberer Weg, Zurücksetzen, aber Protokollieren des Zurücksetzens:

    git revert --strategy resolve <commit>
    
  • Auf harte Weise entfernen Sie insgesamt nur das letzte Commit:

    git reset --soft "HEAD^"
    

Hinweis: Vermeiden git reset --hardSie es, alle Änderungen in Dateien seit dem letzten Festschreiben zu verwerfen. Wenn --softes nicht funktioniert, versuchen Sie es lieber mit --mixedoder --keep.

  • Rebase (zeige das Protokoll der letzten 5 Commits an und lösche die Zeilen, die du nicht willst, oder ordne sie neu an oder quetsche mehrere Commits in einem oder mache alles andere, was du willst. Dies ist ein sehr vielseitiges Tool):

    git rebase -i HEAD~5
    

Und wenn ein Fehler gemacht wird:

git rebase --abort
  • Schnelle Wiederherstellung: Entfernen Sie nur ein bestimmtes Commit mit seiner ID:

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

    git cherry-pick commit-id
    
  • Noch eine Alternative:

    git revert --no-commit
    
  • Als letzten Ausweg können Sie diese sehr schnelle Open-Source-Anwendung verwenden: reposurgeon , wenn Sie die volle Freiheit bei der Bearbeitung des Verlaufs benötigen (z. B. weil Sie mit git nicht bearbeiten können, was Sie möchten) .

Hinweis: Natürlich werden alle diese Änderungen lokal vorgenommen. Anschließend sollten Sie git pushdie Änderungen auf die Fernbedienung anwenden. Und falls Ihr Repo das Commit nicht entfernen möchte ("kein schneller Vorlauf erlaubt", was passiert, wenn Sie ein bereits übertragenes Commit entfernen möchten), können Sie git push -fdie Änderungen erzwingen.

Hinweis 2: Wenn Sie an einem Zweig arbeiten und Push erzwingen müssen, sollten Sie dies unbedingt vermeiden, git push --forceda dies andere Zweige überschreiben kann (wenn Sie Änderungen daran vorgenommen haben, auch wenn sich Ihre aktuelle Kasse in einem anderen Zweig befindet). Geben Sie immer den Remote-Zweig an, wenn Sie Push erzwingen : git push --force origin your_branch.

gaborous
quelle
Basierend auf Vorschlägen von @gaborous: Machen Sie eine "Git Rebase -i HEAD ~ 2". Jetzt haben Sie mehrere Möglichkeiten. Im vim sehen Sie einige kommentierte Zeilen: Eine davon sagt Ihnen, dass Sie einfach eine Zeile löschen können (dies sollte das Commit sein, das Sie entfernen möchten), und dieses Commit wird zusammen mit dem Protokoll in Ihrem Verlauf entfernt.
Ilker Cat
git revert --strategy resolve <commit>. Dieser Befehl hat bei mir funktioniert. danke :)
Swathin
2
git rebase -i HEAD~5arbeitete für mich. Dann habe ich nur die Commits entfernt, die ich nicht brauchte, und konnte das Problem in weniger als 30 Sekunden lösen. Danke dir.
lv10
117

Hier ist eine einfache Lösung:

git rebase -i HEAD~x

(Hinweis: xist die Anzahl der Commits)

Beim Ausführen wird die Editor-Datei geöffnet. Geben Sie dropneben Ihrem Commit ein.
Wenn Sie Vim nicht kennen, klicken Sie einfach auf jedes Wort, das Sie bearbeiten möchten, und drücken Sie dann die Taste "I" (für den Einfügemodus). Wenn Sie mit der Eingabe fertig sind, drücken Sie die Taste "esc", um den Einfügemodus zu verlassen.



Geben Sie hier die Bildbeschreibung ein

und fertig, Sie sind fertig ... Synchronisieren Sie einfach das Git-Dashboard und die Änderungen werden auf Remote übertragen.

Wenn sich das von Ihnen abgelegte Commit bereits auf der Fernbedienung befand, müssen Sie Push erzwingen. Da --force als schädlich angesehen wird , verwenden Sie git push --force-with-lease.

JD-V
quelle
Gibt es eine gute Möglichkeit, herauszufinden, was 'x' sein sollte, wenn Sie nur den Hash des betreffenden Commits kennen?
Jlewkovich
1
Für Menschen mit CPP-Mentalität gilt: x (Anzahl der Commits) ist inklusive. zB HEAD ~ 4 enthält die letzten 4 Commits.
Herpes Free Engineer
perfekter Vorschlag. Ich möchte nur hinzufügen, dies verwirft auch die Änderungen aus dem verworfenen Commit.
Celerno
versuchte 3 Commits zurückzusetzen: git rebase -i HEAD-3 hat einen schwerwiegenden Fehler: Benötigte eine einzelne Revision ungültig vor 'HEAD-3'
Ustin
1
@Ustin es ist ~ 3 nicht -3
JD-V
37

Sie haben die Wahl zwischen

  1. Beibehaltung des Fehlers und Einführung eines Fixes und
  2. Entfernen des Fehlers und Ändern des Verlaufs.

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

Git Revert ist ein automatisiertes Tool (1), das ein neues Commit erstellt und einige vorherige Commits rückgängig macht. Sie werden den Fehler und das Entfernen im Projektverlauf sehen, aber Personen, die aus Ihrem Repository ziehen, werden beim Aktualisieren keine Probleme haben. In Ihrem Beispiel funktioniert dies nicht automatisiert. Sie müssen daher 'myfile' bearbeiten (um Zeile 2 zu entfernen), den Konflikt ausführen git add myfileund git commitbehandeln. Sie erhalten dann vier Commits in Ihrem Verlauf, wobei Commit 4 Commit 2 zurücksetzt.

Wenn es niemanden interessiert, dass sich Ihr Verlauf ändert, können Sie ihn neu schreiben und Commit 2 entfernen (Auswahl 2). Der einfache Weg, dies zu tun, ist zu verwenden git rebase -i 8230fa3. Dadurch werden Sie in einen Editor verschoben, und Sie können festlegen, dass das fehlerhafte Festschreiben nicht eingeschlossen wird, indem Sie das Festschreiben entfernen (und "Auswahl" neben den anderen Festschreibungsnachrichten beibehalten. Informieren Sie sich über die Konsequenzen, die sich daraus ergeben .

Andrew Walker
quelle
Rebase kann schwierig sein, da es sich nach einer Zusammenführung anhört.
Cascabel
3
git rebase -i 8230fa3 und das Löschen der Commit-Zeile haben bei meinen nur lokalen Änderungen hervorragend funktioniert. Vielen Dank!
Samuel
26

Ansatz 1

Holen Sie sich zuerst den Commit-Hash (Beispiel: 1406cd61), den Sie zurücksetzen müssen. einfache Lösung wird unter Befehl sein,

$ git revert 1406cd61

Wenn Sie nach dem Festschreiben von 1406cd61 weitere Änderungen in Bezug auf 1406cd61-Dateien festgeschrieben haben, funktioniert der obige einfache Befehl nicht. Dann müssen Sie die folgenden Schritte ausführen, nämlich Kirschernte.

Ansatz 2

Bitte folgen Sie den folgenden Aktionen. Da wir --force verwenden, müssen Sie über Administratorrechte für das Git-Repo verfügen, um dies zu tun.

Schritt 1: Suchen Sie das Commit vor dem Commit, das Sie entfernen möchtengit log

Schritt 2: Überprüfen Sie das Commitgit checkout <commit hash>

Schritt 3: Erstellen Sie einen neuen Zweig mit Ihrem aktuellen Checkout-Commitgit checkout -b <new branch>

Schritt 4: Jetzt müssen Sie das Commit nach dem entfernten Commit hinzufügengit 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 Commits zu Ihrem neuen Zweig hinzugefügt und festgeschrieben wurden. Überprüfen Sie, ob alles im richtigen Zustand ist und wie vorgesehen funktioniert. Überprüfen Sie noch einmal, ob alles festgeschrieben wurde:git status

Schritt 7: Wechseln Sie zu Ihrem defekten Zweiggit checkout <broken branch>

Schritt 8: Führen Sie nun einen Hard-Reset für den defekten Zweig auf das Commit durch, bevor Sie den entfernen möchtengit reset --hard <commit hash>

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

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

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

tk_
quelle
1
Der erste Ansatz wirkte wie ein Zauber. Es enthält ein Commit, das angibt, dass Ihr gewünschtes Commit zurückgesetzt wurde, was für Tracking-Zwecke sehr hilfreich ist.
Suarsenegger
18

Sie können unerwünschte Commits mit entfernen git rebase. Angenommen, Sie haben einige Commits aus dem Themenzweig eines Kollegen in Ihren Themenzweig aufgenommen, aber später entschieden, dass Sie diese Commits nicht möchten.

git checkout -b tmp-branch my-topic-branch  # Use a temporary branch to be safe.
git rebase -i master  # Interactively rebase against master branch.

Zu diesem Zeitpunkt öffnet Ihr Texteditor die interaktive Rebase-Ansicht. Beispielsweise

git-rebase-todo

  1. Entfernen Sie die nicht gewünschten Commits, indem Sie deren Zeilen löschen
  2. Speichern und Beenden

Wenn die Rebase nicht erfolgreich war, löschen Sie den temporären Zweig und versuchen Sie es mit einer anderen Strategie. Fahren Sie andernfalls mit den folgenden Anweisungen fort.

git checkout my-topic-branch
git reset --hard tmp-branch  # Overwrite your topic branch with the temp branch.
git branch -d tmp-branch  # Delete the temporary branch.

Wenn Sie Ihren Themenzweig auf eine Fernbedienung verschieben, müssen Sie möglicherweise Push erzwingen, da sich der Festschreibungsverlauf geändert hat. Wenn andere an demselben Zweig arbeiten, geben Sie ihnen einen Hinweis.

Dennis
quelle
Könnten Sie bitte ein Beispiel für eine andere Strategie geben?
Pfabri
@pfabri Sie könnten zum Beispiel zwei Bereiche von Commits auswählen, in denen Sie das schlechte Commit weglassen. Sie könnten das schlechte Commit zurücksetzen. Sie können die Verwendung einer Git-Lösung vermeiden, indem Sie die Änderungen sogar manuell rückgängig machen oder von einem neuen Zweig ohne das schlechte Commit ausgehen und die guten Änderungen manuell wiederholen. Wenn das schlechte Commit vertrauliche Daten enthält, benötigen Sie eine sorgfältigere Strategie: help.github.com/en/articles/…
Dennis
8

Aufgrund anderer Antworten hier war ich etwas verwirrt darüber, wie git rebase -iein Commit entfernt werden kann. Ich hoffe, dass es in Ordnung ist, meinen Testfall hier aufzuschreiben (sehr ähnlich dem OP).

Hier ist ein bashSkript, das Sie einfügen können, um ein Test-Repository im /tmpOrdner zu erstellen :

set -x

rm -rf /tmp/myrepo*
cd /tmp

mkdir myrepo_git
cd myrepo_git
git init
git config user.name me
git config user.email me@myself.com

mkdir folder
echo aaaa >> folder/file.txt
git add folder/file.txt
git commit -m "1st git commit"

echo bbbb >> folder/file.txt
git add folder/file.txt
git commit -m "2nd git commit"

echo cccc >> folder/file.txt
git add folder/file.txt
git commit -m "3rd git commit"

echo dddd >> folder/file.txt
git add folder/file.txt
git commit -m "4th git commit"

echo eeee >> folder/file.txt
git add folder/file.txt
git commit -m "5th git commit"

An dieser Stelle haben wir eine file.txtmit folgenden Inhalten:

aaaa
bbbb
cccc
dddd
eeee

Zu diesem Zeitpunkt befindet sich HEAD beim 5. Commit, HEAD ~ 1 wäre das 4. - und HEAD ~ 4 wäre das 1. Commit (also würde HEAD ~ 5 nicht existieren). Angenommen, wir möchten das dritte Commit entfernen - wir können diesen Befehl im myrepo_gitVerzeichnis ausgeben :

git rebase -i HEAD~4

( Beachten Sie, dass die git rebase -i HEAD~5Ergebnisse mit "fatal: Benötigt eine einzelne Revision; ungültiger Upstream-HEAD ~ 5" angezeigt werden . ) Ein Texteditor (siehe Screenshot in der Antwort von @Dennis ) wird mit folgenden Inhalten geöffnet:

pick 5978582 2nd git commit
pick 448c212 3rd git commit
pick b50213c 4th git commit
pick a9c8fa1 5th git commit

# Rebase b916e7f..a9c8fa1 onto b916e7f
# ...

Wir erhalten also alle Commits seit (aber nicht einschließlich ) unserem angeforderten HEAD ~ 4. Löschen Sie die Zeile pick 448c212 3rd git commitund speichern Sie die Datei. Sie erhalten diese Antwort von git rebase:

error: could not apply b50213c... 4th git commit

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To check out the original branch and stop rebasing run "git rebase --abort".
Could not apply b50213c... 4th git commit

Öffnen Sie an dieser Stelle myrepo_git / folder/file.txtin einem Texteditor. Sie werden sehen, dass es geändert wurde:

aaaa
bbbb
<<<<<<< HEAD
=======
cccc
dddd
>>>>>>> b50213c... 4th git commit

Grundsätzlich gitsieht man, dass, als HEAD zum 2. Commit kam, Inhalt von aaaa+ war bbbb; und dann hat es einen Patch mit cccc+ hinzugefügt, ddddden es nicht an den vorhandenen Inhalt anhängen kann.

Also hier gitkönnen Sie sich nicht entscheiden - es ist Sie , die eine Entscheidung zu treffen hat: durch die 3. Entfernen begehen, können Sie entweder die Änderungen , indem sie eingeführt halten (hier die Linie cccc) - oder eben nicht. Wenn Sie dies nicht tun, entfernen Sie einfach die zusätzlichen Zeilen - einschließlich der cccc- in folder/file.txteinem Texteditor, damit es so aussieht:

aaaa
bbbb
dddd

... und dann speichern folder/file.txt. Jetzt können Sie die folgenden Befehle im myrepo_gitVerzeichnis ausgeben :

$ nano folder/file.txt  # text editor - edit, save
$ git rebase --continue
folder/file.txt: needs merge
You must edit all merge conflicts and then
mark them as resolved using git add

Ah - so um Marke , dass wir den Konflikt gelöst haben, wir müssen git add das folder/file.txt, bevor Sie git rebase --continue:

$ git add folder/file.txt
$ git rebase --continue

Hier öffnet sich wieder ein Texteditor, der die Zeile anzeigt 4th git commit- hier haben wir die Möglichkeit, die Commit-Nachricht zu ändern (die in diesem Fall sinnvoll in 4th (and removed 3rd) commitoder ähnlich geändert werden könnte ). Angenommen, Sie möchten nicht - verlassen Sie einfach den Texteditor, ohne zu speichern. Sobald Sie das tun, erhalten Sie:

$ git rebase --continue
[detached HEAD b8275fc] 4th git commit
 1 file changed, 1 insertion(+)
Successfully rebased and updated refs/heads/master.

An diesem Punkt haben Sie jetzt eine solche Historie (die Sie auch mit say gitk .oder anderen Tools überprüfen können) des Inhalts von folder/file.txt(mit anscheinend unveränderten Zeitstempeln der ursprünglichen Commits):

1st git commit  |  +aaaa
----------------------------------------------
2nd git commit  |   aaaa
                |  +bbbb
----------------------------------------------
4th git commit  |   aaaa
                |   bbbb
                |  +dddd
----------------------------------------------
5th git commit  |   aaaa
                |   bbbb
                |   dddd
                |  +eeee

Und wenn wir uns zuvor entschlossen hätten, die Zeile ccccbeizubehalten (der Inhalt des 3. Git-Commits, den wir entfernt haben), hätten wir Folgendes gehabt:

1st git commit  |  +aaaa
----------------------------------------------
2nd git commit  |   aaaa
                |  +bbbb
----------------------------------------------
4th git commit  |   aaaa
                |   bbbb
                |  +cccc
                |  +dddd
----------------------------------------------
5th git commit  |   aaaa
                |   bbbb
                |   cccc
                |   dddd
                |  +eeee

Nun, dies war die Art von Lektüre, von der ich gehofft hatte, dass ich sie gefunden hätte, um herauszufinden, wie das git rebaseLöschen von Commits / Revisionen funktioniert. also hoffe es könnte auch anderen helfen ...

sdaau
quelle
Was für ein unschätzbarer Durchgang - der genaue Anwendungsfall, mit dem ich zu kämpfen hatte, hat mir sehr geholfen.
Pfabri
2

Es hört sich also so an, als ob das schlechte Commit irgendwann in ein Merge-Commit aufgenommen wurde. Wurde Ihr Merge-Commit bereits gezogen? Wenn ja, möchten Sie verwenden git revert; Sie müssen Ihre Zähne zusammenbeißen und die Konflikte bewältigen. Wenn nein, können Sie möglicherweise entweder neu gründen oder zurücksetzen, dies jedoch vor dem Festschreiben der Zusammenführung, und dann die Zusammenführung wiederholen.

Es gibt nicht viel Hilfe, die wir Ihnen für den ersten Fall geben können. Nachdem Sie versucht haben, die Wiederherstellung durchzuführen, und festgestellt haben, dass die automatische Wiederherstellung fehlgeschlagen ist, müssen Sie die Konflikte untersuchen und entsprechend beheben. Dies ist genau der gleiche Vorgang wie das Beheben von Zusammenführungskonflikten. Sie können verwenden, um git statuszu sehen, wo die Konflikte liegen, die nicht zusammengeführten Dateien bearbeiten, die in Konflikt stehenden Hunks finden, herausfinden, wie sie gelöst werden können, die in Konflikt stehenden Dateien hinzufügen und schließlich festschreiben. Wenn Sie git commitselbst verwenden (nein -m <message>), sollte die Nachricht, die in Ihrem Editor angezeigt wird, die Vorlagennachricht sein, die von erstellt wurde git revert. Sie können einen Hinweis hinzufügen, wie Sie die Konflikte behoben haben, und dann speichern und beenden, um ein Commit durchzuführen.

Für den zweiten Fall, bei dem das Problem vor dem Zusammenführen behoben wurde, gibt es zwei Unterfälle, je nachdem, ob Sie seit dem Zusammenführen mehr Arbeit geleistet haben. Wenn Sie dies nicht git reset --hard HEAD^getan haben, können Sie die Zusammenführung einfach abbrechen, die Wiederherstellung durchführen und dann die Zusammenführung wiederholen. Aber ich vermute du hast. Am Ende machen Sie also so etwas:

  • Erstellen Sie kurz vor dem Zusammenführen einen temporären Zweig und checken Sie ihn aus
  • Führen Sie das Zurücksetzen durch (oder verwenden Sie es git rebase -i <something before the bad commit> <temporary branch>, um das fehlerhafte Festschreiben zu entfernen).
  • Wiederholen Sie die Zusammenführung
  • Stellen Sie Ihre nachfolgende Arbeit wieder auf: git rebase --onto <temporary branch> <old merge commit> <real branch>
  • Entfernen Sie den temporären Zweig
Cascabel
quelle
1

Also haben Sie einige Arbeiten ausgeführt und sie vorangetrieben. Nennen wir sie Commits A und B. Ihr Mitarbeiter hat auch einige Arbeiten ausgeführt, C und D festgeschrieben. Auch (Commit F) und festgestellt, dass Ihr Mitarbeiter einige Dinge geändert hat, die er nicht haben sollte.

Ihr Commit-Verlauf sieht also folgendermaßen aus:

A -- B -- C -- D -- D' -- E -- F

Sie wollen wirklich C, D und D 'loswerden. Da Sie sagen, dass Sie die Arbeit Ihrer Mitarbeiter in Ihre Arbeit integriert haben, sind diese Commits bereits "da draußen". Das Entfernen der Commits mithilfe von z. B. git rebase ist also ein Nein-Nein. Glauben Sie mir, ich habe es versucht.

Jetzt sehe ich zwei Auswege:

  • Wenn Sie E und F noch nicht an Ihren Kollegen oder an eine andere Person (normalerweise Ihren "Ursprungs" -Server) gesendet haben, können Sie diese vorerst noch aus dem Verlauf entfernen. Dies ist Ihre Arbeit, die Sie speichern möchten. Dies kann mit einem erfolgen

    git reset D'
    

    (Ersetzen Sie D 'durch den tatsächlichen Commit-Hash, den Sie von a erhalten können git log

    Zu diesem Zeitpunkt sind die Commits E und F weg und die Änderungen sind wieder nicht festgeschriebene Änderungen in Ihrem lokalen Arbeitsbereich. An diesem Punkt würde ich sie in einen Zweig verschieben oder in einen Patch verwandeln und für später speichern. Setzen Sie jetzt die Arbeit Ihres Kollegen entweder automatisch mit git revertoder manuell zurück. Wenn Sie das getan haben, spielen Sie Ihre Arbeit noch einmal ab. Möglicherweise haben Sie Zusammenführungskonflikte, aber zumindest befinden sie sich in dem Code, den Sie geschrieben haben, anstelle des Codes Ihres Kollegen.

  • Wenn Sie die Arbeit, die Sie nach den Commits Ihres Kollegen geleistet haben, bereits vorangetrieben haben, können Sie trotzdem versuchen, entweder manuell oder mithilfe eines "Reverse Patch" zu erhalten git revert, aber da Ihre Arbeit sozusagen "im Weg" ist, werden Sie wahrscheinlich so etwas bekommen mehr Zusammenführungskonflikte und verwirrendere. Sieht so aus, als wären Sie dort gelandet ...

Frans
quelle
0

git revert --strategy Auflösung, wenn Commit eine Zusammenführung ist: Verwenden Sie git revert --strategy Auflösung -m 1

ShaDow RiDeR
quelle