Wie kann ich das letzte Commit in einem Git Bare-Repository aufheben?

91

In Anbetracht der Tatsache, dass es mehrere Git-Befehle gibt, die in einem Bare-Repository keinen Sinn ergeben (da Bare-Repositorys keine Indizes verwenden und kein Arbeitsverzeichnis haben),

git reset --hard HEAD^ 

ist keine Lösung, um die letzte Änderung in einem solchen Repository aufzuheben.

Die Suche über das Internet, alles , was ich zu dem Thema finden konnte , ist dies , in dem ich vorgestellt habe drei Möglichkeiten , dies zu tun:
1. „den Referee manuell aktualisieren (die Sanitär beinhaltet)“;
2. " git push -faus einem nicht nackten Repository";
3. " git branch -f this $that".

Welche Lösung halten Sie für angemessener oder welche anderen Möglichkeiten gibt es dafür? Leider ist die Dokumentation, die ich über Git Bare Repositories gefunden habe, ziemlich schlecht.

Lavinia-Gabriela Dobrovolschi
quelle
7
@ Lavinia-Garbriela Dobrovol Verwenden Sie nicht die komplizierten Sachen unten. Sie versuchen, HEAD auf ein anderes Commit zu verschieben, und genau dafür ist das Zurücksetzen von Git vorgesehen, selbst in einem nackten Repo. Verwenden Sie gemäß meiner Antwort unten: git reset --soft <commit> Mit --soft versuchen Sie nicht, einen Arbeitsbaum und einen Index zu ändern, die nicht vorhanden sind. Mit git können Sie das Zurücksetzen also problemlos durchführen.
Hazok

Antworten:

129

Sie können den git update-refBefehl verwenden. Um das letzte Commit zu entfernen, verwenden Sie:

$ git update-ref HEAD HEAD^

Oder wenn Sie sich nicht in dem Zweig befinden, aus dem Sie das letzte Commit nicht entfernen können:

$ git update-ref refs/heads/branch-name branch-name^

Sie können auch eine sha1 übergeben, wenn Sie möchten:

$ git update-ref refs/heads/branch-name a12d48e2

Siehe die Dokumentation des Befehls git-update-ref .

Sylvain Defresne
quelle
@ Lavinia-Gabriela Dobrovolschi: Richtig, ich war mit der genauen Syntax nicht vertraut.
VonC
@VonC Sie können die <ref> in git update-ref <ref> <newvalue>als richtigen Zweig angeben , z. B. "refs / Heads / Master" anstelle von HEAD. Ich hoffe, ich habe Ihre Frage nicht falsch verstanden.
Lavinia-Gabriela Dobrovolschi
@ Sylvain: +1 gute Bearbeitung. @ Lavinia-Gabriela Dobrovolschi danke für die Präzision. Das ist viel praktischer (wenn Sie einen direkten Zugriff auf den Remote-Server haben, nehme ich an).
VonC
3
Die Beispiele sind in Bezug auf das branch-nameArgument irreführend . Bei Verwendung update-refmit einem „Zweig“ müssen Sie unbedingt den vollständigen Referenznamen des Zweigs angeben (dh refs/heads/vor dem normalen kurzen Zweignamen ). Wenn Sie nur die Kurznamen verwenden , werden Sie am Ende der Erstellung / Aktualisierung $GIT_DIR/branch-namestatt $GIT_DIR/refs/heads/branch-name. Das Vorhandensein von beiden branch-nameund refs/heads/branch-nameführt zu "refname ... ist mehrdeutig" Warnungen.
Chris Johnsen
Diese Antwort ist viel komplizierter als das, was Zach vorgeschlagen hat. Und seine Lösung funktioniert gut.
Krystian
31

Wenn Sie in einem Bare Repo Folgendes verwenden:

git reset --soft <commit>

Dann stoßen Sie nicht auf die Probleme --hardund --mixedOptionen, die Sie in einem Bare-Repo verwenden, da Sie nicht versuchen, etwas zu ändern, das das Bare-Repo nicht hat (dh Arbeitsbaum und Index). In Ihrem Fall möchten Sie speziell (aus dem Bare Repo) verwenden:

git reset --soft HEAD^

So wechseln Sie die Zweige auf dem Remote-Repo :

git symbolic-ref HEAD refs/heads/<branch_name>

Um den aktuell ausgewählten Zweig anzuzeigen, verwenden Sie:

git symbolic-ref HEAD

https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-symbolic-ref.html

Hazok
quelle
3
Wie wählen Sie den Zweig aus, den Sie verschieben möchten? Ihr Beispiel funktioniert gut auf dem Master, git checkout other_branchfunktioniert aber nicht im nackten Zustand.
Gauthier
1
Hmmm ... ich frage mich, wer mich dafür abgewählt hat. Bei der Frage wurde nicht gefragt, wie Zweige auf einem Remote-Repo gewechselt werden sollen, sondern wie auf einem Bare-Repo zurückgesetzt werden soll. Verwenden Sie zum Ändern des Standardzweigs in einem Remote-Repo git symbolic-ref HEAD refs / Heads / <branch_name>.
Hazok
7

Das git push -fsollte gut funktionieren:
Wenn Sie dieses Bare-Repo klonen, entfernen Sie das letzte Commit ( git reset --hard HEAD^wie Sie erwähnen, aber in einem lokalen nicht-Bare-Repo) und drücken Sie zurück ( -f):

  • Sie ändern kein SHA1 für die anderen Commits vor dem von Ihnen entfernten.
  • Sie sind sicher, dass Sie den genauen Inhalt des Bare Repo abzüglich des zusätzlichen Commits zurückschieben (weil Sie es gerade erst geklont haben).
VonC
quelle
@ VonC Hallo Von, ich habe gesehen, dass du viel auf Git geantwortet hast, also wollte ich dich fragen ... Ich war neugierig, warum sollte nicht, git reset --soft <sha1>wie in meiner Antwort unten gezeigt, die empfohlene Vorgehensweise sein, um HEAD auf einem nackten Repo zu bewegen?
Hazok
Ich denke, ein weiterer Grund, den ich frage, ist, dass die Verwendung von Soft-Reset für nackte Repos keine Informationen sind, die leicht verfügbar sind, und viele Foren unnötig komplexe Problemumgehungen zu haben scheinen, wenn es so aussieht, als ob Soft-Reset aufgrund des geringsten Tippaufwands und der geringsten Wahrscheinlichkeit die beste Vorgehensweise ist für Fehler.
Hazok
2
@Zach: a reset --softsollte funktionieren, wenn es direkt auf einem nackten Repo gemacht wird. Ich vermute, dass dies selten gemacht wird, da ein nacktes Repo im Allgemeinen ein Upstream-Repo ist (dh ein Repo, an das Sie Daten senden), und die meiste Zeit haben Sie keinen direkten lokalen Zugriff darauf. Wenn Sie dies jedoch tun, ist dies sicherlich ein weiteres gutes Beispiel für die reset --softVerwendung von " " (wie in stackoverflow.com/questions/5203535/… ). Also +1 auf Ihre Antwort.
VonC
2

Sie können auch die Git-Refspec-Notation verwenden und Folgendes tun:

git push -f origin +<commit you want to revert to>:<destination_head | branch_name>

Dies erzwingt die Aktualisierung des Zielzweigs (wie durch den Verweis angegeben) auf das Quell-Commit, wie durch das +<object ref>Teil angegeben.

alup
quelle
2
außer wenn es eine acl auf dem Zweig gibt - was normalerweise der Fall ist, wenn Sie "es auf dem nackten Repo selbst tun müssen" ...
David Schmitt