Durchsuchen Sie verwaiste Commits in Git

102

Mein Git-Repository ist irgendwie wackelig geworden - ich habe heute Morgen msysgit geladen und anstatt den Filialnamen nach dem aktuellen Verzeichnis anzuzeigen, heißt es "((ref: re ...))", 'git status' meldet alles als Neue Datei, 'Git Log' und 'Git Reflog' sagen mir "fatal: schlechte Standardrevision 'HEAD'" und so weiter.

Wenn ich 'git reflog --all' oder 'gitk --all' mache, sehe ich, dass der Rest des Repositorys intakt ist, aber es sieht so aus, als wäre der Zweig, an dem ich gearbeitet habe, gerade verschwunden, was erklärt, warum HEAD nicht zu existieren scheint / auf irgendetwas zeigen.

Ich weiß, dass git alle Arten von Informationen enthält, und ich gehe davon aus, dass meine Commits gerade irgendwie verwaist sind. Gibt es also einen Befehl, der mir diese Commits anzeigt, damit ich HEAD auf sie zurücksetzen kann?

EDIT: Oh je. Ich habe 'git fsck' entdeckt und 'git fsck --full' meldet "fatal: Objekt 03ca4 ... ist beschädigt". Was zum Teufel kann ich dagegen tun?

EDIT: Oh je, oh je. Ich habe einen anderen Zweig ausgecheckt und dann versucht, den ursprünglichen Zweig mit demselben Namen mithilfe von 'git checkout -b lostbranchname' neu zu erstellen. Git sagt "Fehler: Referenzreferenzen / Köpfe / verlorener Zweigname können nicht aufgelöst werden: Kein Fehler, schwerwiegend: Fehlgeschlagen Ref für Update sperren: Kein Fehler ". 'Kein Fehler' muss ein besonders böser Fehler sein. Es sieht also so aus, als ob es immer noch herumhängt, aber nicht benutzt und nicht getötet werden kann.

EDIT: Super Duper oh je. Ich habe einige Dinge entpackt, neu gepackt und ersetzt, wie hier vorgeschlagen: Wie kann ich Git-Objekte wiederherstellen, die durch einen Festplattenausfall beschädigt wurden? , aber jetzt bekomme ich einen weiteren Hash, der als korrupt gemeldet wird, für etwas so Unschädliches wie "Git-Status". Ich denke, das Ganze ist abgespritzt. Git ist reizend und alles, aber ich sollte mich nicht mit so etwas befassen müssen.

Ben Hymers
quelle
In Bezug auf git checkout -b lostbranchname- wenn Sie nur über den Namen der Branche (nicht der Inhalt davon) kümmern, können Sie manuell löschen (oder umbenennen) .git/refs/heads/lostbranchname-, die den Trick hoffentlich tun wird.
Antony Hatchkins
1
Und Sie haben keinen Upstream, in den Sie diesen Git-Ordner verschieben?
Lakshman Prasad
1
Leider nicht, es ist tatsächlich eine Art Ersatz-Repository für ein minderwertiges Versionsverwaltungssystem. Ich verwende es nur lokal, um alle Funktionen und Feinheiten von git ohne den Aufwand des anderen Systems zu erhalten. Aber zumindest das andere System beschädigt sich nicht zufällig. Das bedeutet jedoch, dass ich nur meine Änderungen verloren habe, seit ich das letzte Mal bei dem anderen System eingecheckt habe, das ich bereits wiederhergestellt habe. Zeit, ein neues Repository zu starten!
Ben Hymers
7
Ich würde zögern zu sagen, dass Git dich dazu gebracht hat, "mit so etwas umzugehen" oder dass es sich selbst korrumpiert hat. Nichts außer einem Backup kann gegen Datenverlust vollständig stabil sein.
Cascabel
1
Ich weiß wirklich, ich bin nur (natürlich) ein bisschen verärgert, dass ich meine hübsche Geschichte verloren habe. Es ist nicht Git's Schuld, jedes andere System würde sich bei gegebenen Dateisystemfehlern genauso verhalten.
Ben Hymers

Antworten:

134

Anstatt dies offen zu lassen, denke ich, werde ich eine Antwort auf meine eigene Frage geben. Die Verwendung git reflog --allist eine gute Möglichkeit, verwaiste Commits zu durchsuchen. Mit den SHA1-Hashes können Sie den Verlauf rekonstruieren.

In meinem Fall war das Repository jedoch beschädigt, sodass dies nicht half. git fsckkann Ihnen helfen, Fehler im Repository selbst zu finden und manchmal zu beheben.

Ben Hymers
quelle
3
Vielen Dank. Dies ist der einzige Ort, an dem ich diese Informationen gefunden habe, als ich versucht habe, eine verwaiste Pull-Anfrage auf Github zu ziehen. Mein Problem gelöst.
SystemParadox
6
für den Fall, dass jemand alles in gitk haben möchte: [alias] orphank = !gitk --all --date-order ``git reflog | cut -c1-7``&(Bearbeiten: Stellen Sie sich diese doppelten Backticks vor, bei denen einzelne - Flucht hier nicht zu funktionieren scheint)
mbx
1
Super Tipp @mbx! Sehr nützlich, um die Verknüpfungen zwischen verwaisten Commits grafisch anzeigen zu können!
Ben Hymers
@BenHymers Wäre cool, wenn wir auch gepunktete Linien für "Rebase / Squash" -ähnliche Commit-Beziehungen bekommen könnten. Ich habe noch keinen Weg gefunden, das zu tun.
mbx
Ich wusste nichts über Reflog, als ich die Antwort oben schrieb. Es ist so ein nützliches Werkzeug!
Jamey Hicks
17

Mit git 2.9.x / 2.10 (Q3 2016) müssen Sie nicht git reflog --allmehr verwenden, git reflogwird ausreichen.

Siehe Commit 71abeb7 (03. Juni 2016) von SZEDER Gábor ( szeder) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 7949837 , 06. Juli 2016)

reflog: Gehen Sie weiter die reflogletzten Root-Commits

Wenn ein Repository mehr als ein Root-Commit enthält, kann sein HEAD-Reflog mehrere "Erstellungsereignisse" enthalten, dh Einträge, deren "Von" -Wert Null sha1 ist.
Das Auflisten eines solchen Reflogs wird derzeit beim ersten derartigen Eintrag vorzeitig beendet, selbst wenn das Reflog noch ältere Einträge enthält.
Dies kann Benutzer zu der Annahme verleiten, dass ihr Reflog nach ' git checkout --orphan' abgeschnitten wurde .

Gehen Sie den Reflog weiter an solchen Erstellungsereignissen vorbei, basierend auf dem "neuen" Wert des vorherigen Reflog-Eintrags.

VonC
quelle
4

Ein gutes Merkmal von Git ist, dass es Korruption erkennt. Es enthält jedoch keine Fehlerkorrektur zum Schutz vor Beschädigung.

Ich hoffe, dass Sie den Inhalt dieses Repositorys auf einen anderen Computer übertragen haben oder dass Sie Backups haben, um die beschädigten Teile wiederherzustellen.

Ich habe keine Erfahrung mit Git unter Windows, habe aber noch nie ein solches Verhalten mit Git unter Linux oder OS X gesehen.

Jamey Hicks
quelle
2

Ich finde die git reflogAusgabe normalerweise verwirrend. Es ist für mich viel einfacher, ein Commit-Diagramm zu verstehen aus git log --graph --reflog:

$ git alias graph "log --graph --all --format='%h %s%n        (%an, %ar)%d' --abbrev-commit
$ git graph --reflog

* f06abeb Add feature
|         (Sue Dakota, 4 days ago) (HEAD -> master)
* f126291 Fix the build
|         (Oski M. Wizard, 4 days ago) (origin/master, master)
* 3c4fb9c Break the build
|         (Alyssa P. Hacker, 4 weeks ago)
| * e3124bf fixup! More work for feature
| |         (Sue Dakota, 4 days ago)
| | * 6a7a52e Lost commit
| |/          (Sue Dakota, 4 days ago)
| * 69d9438 More work for feature
| |         (Sue Dakota, 2 weeks ago)
| * 8f69aba Initial work for feature
|/          (Sue Dakota, 4 weeks ago)
* d824fa9 Fix warnings from the linter
|         (Theo Ristudent, 4 weeks ago)
* 9f782b8 Fix tests flakes
|         (Tess Driven, 4 weeks ago)

und es ist klar, dass e3124bfund 6a7a52esind nicht referenzierte Waisen, und es gibt Kontext von ihren Vorfahren Commits.

Jamesdlin
quelle
Hat mir gerade Stunden verlorener Arbeit erspart! versehentlich eine lokale Filiale gelöscht, auf der Commits git reflog --allnicht verschoben wurden, wird nicht angezeigt , da git log --graph --reflogsie sehr gut sichtbar waren ...
Adam.Er8