Wie mache ich einen erfolgreichen „Git Cherry-Pick“ rückgängig?

95

Auf einem lokalen Repo habe ich gerade ausgeführt git cherry-pick SHA ohne Konflikte oder Probleme ausgeführt. Dann wurde mir klar, dass ich nicht das tun wollte, was ich gerade getan hatte. Ich habe das nirgendwo geschoben.

Wie kann ich nur diesen Kirschpickel entfernen?

Ich würde gerne wissen, ob es einen Weg gibt, dies zu tun:

  • wenn ich andere lokale Änderungen habe
  • wenn ich keine anderen lokalen Änderungen habe

Vorzugsweise mit einem Befehl für beide Fälle, wenn möglich.

Brad Parks
quelle

Antworten:

129

Ein Cherry-Pick ist im Grunde ein Commit. Wenn Sie ihn also rückgängig machen möchten, machen Sie den Commit einfach rückgängig.

wenn ich andere lokale Änderungen habe

Bewahren Sie Ihre aktuellen Änderungen auf, damit Sie sie nach dem Zurücksetzen des Commits erneut anwenden können.

$ git stash
$ git reset --hard HEAD^
$ git stash pop  # or `git stash apply`, if you want to keep the changeset in the stash

wenn ich keine anderen lokalen Änderungen habe

$ git reset --hard HEAD^
Tim
quelle
6
Nur zusätzlich zu der Frage und der Antwort, wenn Sie nicht sicher sind, was Sie Kirschen pflücken, können Sie immer "Kirschpflücken SHA --no-commit" und es gibt keine Commit-nur-Änderungen, die leicht überprüft werden können , dies ist nützlich für teilweise Kirschernte
Kuskmen
1
Windows: Git Reset - Hard "HEAD ^"
schlank
21

Um Ihr letztes Commit rückgängig zu machen, tun Sie es einfach git reset --hard HEAD~.

Bearbeiten : Diese Antwort galt für eine frühere Version der Frage, in der die Beibehaltung lokaler Änderungen nicht erwähnt wurde. Die akzeptierte Antwort von Tim ist in der Tat die richtige. Danke an qwertzguy für das Heads Up.

David Deutsch
quelle
2
Das sollte HEAD ^ oder HEAD ~ 1 sein
Andreas Wederbrand
Sie sind beide gleichbedeutend mit HEAD ~ (und HEAD ^ 1)
David Deutsch
1
@DavidDeutsch Das stimmt (allerdings nur in neueren Versionen von Git), aber Großbuchstaben ( HEAD) sind robuster: Betrachten Sie den unglücklichen Fall, in dem headder Name einer vorhandenen Referenz steht.
Jub0bs
1
@Jubobs - guter Punkt; Ich habe das Gehäuse in meiner Antwort geändert.
David Deutsch
1
@qwertzguy, guter Fang; Mit Blick auf die Zeitstempel wurde der Frage eine Minute, nachdem ich diese Antwort gepostet hatte, das Bit über lokale Änderungen hinzugefügt :)
David Deutsch
8

Vermeiden Sie nach Möglichkeit Hard-Resets. Hard Resets sind eine der wenigen zerstörerischen Operationen in Git. Glücklicherweise können Sie einen Kirschpflücker ohne Zurücksetzen rückgängig machen und alles Zerstörerische vermeiden.

Beachten Sie den Hash der Kirschpickel, die Sie rückgängig machen möchten ${bad_cherrypick}. Mach agit revert ${bad_cherrypick} . Jetzt ist der Inhalt Ihres Arbeitsbaums so, wie er vor Ihrem schlechten Kirschbaum war.

Wiederholen Sie Ihren Vorgang git cherry-pick ${wanted_commit}, und wenn Sie mit dem neuen Kirschpickel zufrieden sind, tun Sie a git rebase -i ${bad_cherrypick}~1. Löschen Sie während des Rebases beide${bad_cherrypick} und den entsprechenden Revert.

Der Zweig, an dem Sie arbeiten, hat nur den guten Kirschbaum. Keine Resets erforderlich!

Cuadue
quelle
6

git reflog kann zu Ihrer Rettung kommen.

Geben Sie es in Ihre Konsole ein und Sie erhalten eine Liste Ihres Git-Verlaufs zusammen mit SHA-1, das diese darstellt.

Überprüfen Sie einfach alle SHA-1, zu denen Sie zurückkehren möchten


Bevor wir antworten, fügen wir einige Hintergrundinformationen hinzu und erklären, was dies ist HEAD.

First of all what is HEAD?

HEADist einfach ein Verweis auf das aktuelle Commit (aktuell) in der aktuellen Verzweigung.
Es kann immer nur eine einzige HEADgeben. (ohnegit worktree )

Der Inhalt von HEADwird im Inneren gespeichert .git/HEADund enthält die 40 Bytes SHA-1 des aktuellen Commits.


detached HEAD

Wenn Sie sich nicht im letzten Commit befinden, bedeutet dies, dass HEADauf ein vorheriges Commit in der Geschichte verwiesen wird detached HEAD.

Geben Sie hier die Bildbeschreibung ein

In der Befehlszeile sieht es so aus: SHA-1 anstelle des Zweignamens, da der HEADnicht auf die Spitze des aktuellen Zweigs zeigt

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Einige Optionen zur Wiederherstellung nach einem abgetrennten KOPF:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Dadurch wird ein neuer Zweig ausgecheckt, der auf das gewünschte Commit verweist.
Dieser Befehl checkt zu einem bestimmten Commit aus.
An diesem Punkt können Sie einen Zweig erstellen und ab diesem Punkt mit der Arbeit beginnen.

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Sie können das auch immer verwenden reflog.
git reflogzeigt jede Änderung an, die das aktualisiert hat, HEADund das Auschecken des gewünschten Reflog-Eintrags setzt HEADdiesen Commit zurück.

Jedes Mal, wenn der KOPF geändert wird, wird ein neuer Eintrag in der reflog

git reflog
git checkout HEAD@{...}

Dadurch kehren Sie zu Ihrem gewünschten Commit zurück

Geben Sie hier die Bildbeschreibung ein


git reset --hard <commit_id>

"Bewegen" Sie Ihren HEAD zurück zum gewünschten Commit.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • Hinweis: ( Seit Git 2.7 ) können
    Sie auch das verwenden git rebase --no-autostash.

git revert <sha-1>

"Rückgängig machen" des angegebenen Commits oder Commit-Bereichs.
Der Befehl zum Zurücksetzen "macht" alle Änderungen rückgängig, die im angegebenen Commit vorgenommen wurden.
Ein neues Commit mit dem Undo-Patch wird festgeschrieben, während das ursprüngliche Commit ebenfalls im Verlauf verbleibt.

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Dieses Schema zeigt, welcher Befehl was tut.
Wie Sie dort sehen können, reset && checkoutändern Sie die HEAD.

Geben Sie hier die Bildbeschreibung ein

CodeWizard
quelle
vielleicht hinzufügengit reset --hard
wyx
3

Angesichts des gleichen Problems stellte ich fest, dass Sie die SHA des Kirschpflückers finden, indem Sie Folgendes ausführen, wenn Sie sich seit Ihrem erfolgreichen Kirschpflücken verpflichtet und / oder auf die Fernbedienung verschoben haben und diese entfernen möchten.

git log --graph --decorate --oneline

Dann können Sie (nach :wqdem Beenden des Protokolls) den Kirschpflücker mit entfernen

git rebase -p --onto YOUR_SHA_HERE^ YOUR_SHA_HERE

wo YOUR_SHA_HERE entspricht die 40- oder abgekürzte 7-Zeichen-SHA des von Kirschen gepflückten Commits.

Zunächst können Sie Ihre Änderungen nicht weitergeben, da Ihr Remote-Repo und Ihr lokales Repo unterschiedliche Commit-Historien haben. Sie können Ihre lokalen Commits dazu zwingen, die Daten auf Ihrer Fernbedienung durch zu ersetzen

git push --force origin YOUR_REPO_NAME

(Ich habe diese Lösung von Seth Robertson angepasst : Siehe "Entfernen eines gesamten Commits".)

Brogrammer
quelle
1

Ein Befehl und verwendet nicht den destruktiven git resetBefehl:

GIT_SEQUENCE_EDITOR="sed -i 's/pick/d/'" git rebase -i HEAD~ --autostash

Es lässt einfach das Commit fallen und versetzt Sie genau in den Zustand vor dem Cherry-Pick zurück, selbst wenn Sie lokale Änderungen hatten.

qwertzguy
quelle
Das Commit wird einfach gelöscht. Was denkst du git reset HEAD^macht?
Tim
@TimCastelijns git resetmacht die Festschreibungsaktion rückgängig, ohne die Änderungen zu löschen . Ich empfehle Ihnen, git-scm.com/docs/git-reset zu lesen . Die Frage von OP ist, einen Kirschbaum rückgängig zu machen. Probieren Sie beide Befehle aus. Mein Befehl versetzt Sie wieder in den Zustand, in dem Sie sich vor dem Kirschpflücken befanden. git resetwird Ihren Arbeitsbaum durcheinander bringen, da er die von Kirschen gepflückten Änderungen hinterlässt und sie nicht mehr von Ihren bereits vorhandenen lokalen Änderungen zu unterscheiden sind.
qwertzguy
Ja, Entschuldigung, ich meinte reset --hard. Es hinterlässt keine Änderungen
Tim
1
@TimCastelijns git reset --hardist ein destruktiver Befehl, der auch nicht verwandte lokale Änderungen entfernt und dies auf nicht wiederherstellbare Weise tut! Das hat das OP also nicht verlangt.
qwertzguy
2
Diese Antwort wäre viel nützlicher, wenn Sie erklären würden, was dieser sedBefehl tut, wie sich dieser von der manuellen Ausführung unterscheidet und was er --autostashtut.
Chris Seite