Ich versuche meine Arbeit wiederzugewinnen. Ich habe es dumm gemacht git reset --hard
, aber vorher habe ich nur getan get add .
und nicht getan git commit
. Bitte helfen Sie! Hier ist mein Log:
MacBookPro:api user$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
# modified: .gitignore
...
MacBookPro:api user$ git reset --hard
HEAD is now at ff546fa added new strucuture for api
Ist es git reset --hard
in dieser Situation möglich, rückgängig zu machen ?
Antworten:
Sie sollten in der Lage sein, alle Dateien wiederherzustellen, die Sie dem Index hinzugefügt haben (z. B. wie in Ihrer Situation mit
git add .
), obwohl dies möglicherweise ein wenig Arbeit ist. Um dem Index eine Datei hinzuzufügen, fügt git sie der Objektdatenbank hinzu. Dies bedeutet, dass sie wiederhergestellt werden kann, solange die Speicherbereinigung noch nicht erfolgt ist. Ein Beispiel dafür finden Sie in Jakub Narębskis Antwort hier:Ich habe das jedoch in einem Test-Repository ausprobiert, und es gab ein paar Probleme -
--cached
sollte es sein--cache
, und ich stellte fest, dass das.git/lost-found
Verzeichnis nicht tatsächlich erstellt wurde . Die folgenden Schritte haben jedoch bei mir funktioniert:Das sollte alle Objekte in der Objektdatenbank ausgeben, die mit keinem Verweis, im Index oder über das Reflog erreichbar sind. Die Ausgabe sieht ungefähr so aus:
... und für jeden dieser Blobs können Sie Folgendes tun:
So geben Sie den Inhalt der Datei aus
Zu viel Output?
Update als Antwort auf den Kommentar von sehe unten:
Wenn Sie feststellen, dass in der Ausgabe dieses Befehls viele Commits und Bäume aufgeführt sind, möchten Sie möglicherweise alle Objekte aus der Ausgabe entfernen, auf die aus nicht referenzierten Commits verwiesen wird. (Normalerweise können Sie über das Reflog ohnehin zu diesen Commits zurückkehren. Wir sind nur an Objekten interessiert, die dem Index hinzugefügt wurden, aber niemals über ein Commit gefunden werden können.)
Speichern Sie zunächst die Ausgabe des Befehls mit:
Jetzt können die Objektnamen dieser nicht erreichbaren Commits gefunden werden mit:
Sie können also nur die Bäume und Objekte finden, die dem Index hinzugefügt, aber zu keinem Zeitpunkt festgeschrieben wurden, mit:
Das reduziert die Anzahl der Objekte, die Sie berücksichtigen müssen, enorm.
Update: Philip Oakley unten schlägt eine andere Möglichkeit vor, die Anzahl der zu berücksichtigenden Objekte zu verringern, nämlich nur die zuletzt geänderten Dateien unter
.git/objects
. Sie finden diese mit:(Ich habe diesen
find
Aufruf hier gefunden .) Das Ende dieser Liste könnte folgendermaßen aussehen:In diesem Fall können Sie diese Objekte sehen mit:
(Beachten Sie, dass Sie das
/
am Ende des Pfads entfernen müssen , um den Objektnamen zu erhalten.)quelle
Ich habe gerade ein
git reset --hard
Commit gemacht und ein Commit verloren. Aber ich kannte den Commit-Hash, also konnte ich es tungit cherry-pick COMMIT_HASH
wiederherstellen.Ich habe dies innerhalb weniger Minuten nach dem Verlust des Commits getan, sodass es für einige von Ihnen möglicherweise funktioniert.
quelle
git reflog
zBgit reset --hard
-> sehen könnengit reflog
( HEAD @ {1} Hash) und schließlichgit cherry-pick COMMIT_HASH
git reset --hard
(vorausgesetzt, Sie haben nach diesem Befehl nichts mehr getan) istgit reset --hard @{1}
Dank Mark Longair habe ich meine Sachen zurückbekommen!
Zuerst habe ich alle Hashes in einer Datei gespeichert:
Als nächstes füge ich sie alle (Entfernen des 'nicht erreichbaren Blobs') in eine Liste ein und füge die Daten alle in neue Dateien ein ... Sie müssen Ihre Dateien auswählen und sie erneut umbenennen, was Sie brauchen ... aber ich brauchte nur einige Dateien ... hoffentlich hilft das jemandem ...
quelle
mkdir lost; git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") | grep -Po '\s\S{40}$' | xargs -i echo "git show {} > lost/{}.blob" | sh
. Dateien werden inlost/*.blob
Die Lösung von @ Ajedi32 in den Kommentaren hat in genau dieser Situation für mich funktioniert.
Beachten Sie, dass alle diese Lösungen davon abhängen, dass es kein git gc gibt, und einige von ihnen möglicherweise eines verursachen. Daher würde ich den Inhalt Ihres .git-Verzeichnisses komprimieren, bevor Sie etwas versuchen, damit Sie einen Snapshot haben, zu dem Sie zurückkehren können, wenn dies nicht der Fall ist Ich arbeite nicht für dich.
quelle
git reset --hard
, die mein Repo auf unbekannte Weise durcheinander gebracht hat. @Duncan, was macht der @ {1}? und auf welchen Kommentar beziehen Sie sich? Wird a zurückgesetztgit reset
?Ist auf dasselbe Problem gestoßen, hat aber die Änderungen nicht zum Index hinzugefügt. Alle obigen Befehle brachten mir also nicht die gewünschten Änderungen zurück.
Nach all den oben ausgearbeiteten Antworten ist dies ein naiver Hinweis, aber es kann sein, dass er jemanden rettet, der nicht wie ich zuerst darüber nachgedacht hat.
In meiner Verzweiflung habe ich versucht, in meinem Editor (LightTable) einmal in jedem geöffneten Tab STRG-Z zu drücken. Glücklicherweise wurde die Datei in diesem Tab auf den neuesten Stand vor dem zurückgesetzt
git reset --hard
. HTH.quelle
Dies ist wahrscheinlich für die Git-Profis da draußen offensichtlich, aber ich wollte es aufstellen, da ich bei meiner hektischen Suche nicht gesehen habe, dass dies zur Sprache gebracht wurde.
Ich habe einige Dateien
git reset --hard
bereitgestellt und eine ausgeführt , bin ein wenig ausgeflippt und habe dann festgestellt, dass in meinem Status alle noch bereitgestellten Dateien sowie alle nicht bereitgestellten Löschvorgänge angezeigt wurden.Zu diesem Zeitpunkt können Sie diese bereitgestellten Änderungen festschreiben, solange Sie ihre Löschvorgänge nicht durchführen. Danach müssen Sie nur noch den Mut aufbringen, dies noch
git reset --hard
einmal zu tun , was Sie zu den Änderungen zurückbringt, die Sie vorgenommen und jetzt nur noch begangen haben.Auch dies ist für die meisten wahrscheinlich nichts Neues, aber ich hoffe, dass es jemand anderem helfen könnte, da es mir geholfen hat und ich nichts gefunden habe, was darauf hindeutet.
quelle
Meine Güte, ich zog an meinen Haaren, bis ich auf diese Frage und ihre Antworten stieß. Ich glaube, die richtige und prägnante Antwort auf die gestellte Frage ist nur verfügbar, wenn Sie zwei der obigen Kommentare zusammenfassen. Hier ist also alles an einem Ort:
Führen Sie, wie von chilicuil erwähnt,
git reflog
den Commit-Hash aus, zu dem Sie zurückkehren möchtenWie von akimsko erwähnt, möchten Sie wahrscheinlich NICHT Kirschbaum pflücken, es sei denn, Sie haben nur ein Commit verloren, also sollten Sie dann laufen
git reset --hard <hash-commit-you-want>
Hinweis für egit Eclipse-Benutzer: Ich konnte mit egit keine Möglichkeit finden, diese Schritte in Eclipse auszuführen. Das Schließen von Eclipse, das Ausführen der obigen Befehle in einem Terminalfenster und das erneute Öffnen von Eclipse funktionierten für mich einwandfrei.
quelle
Die oben genannten Lösungen können funktionieren, es gibt jedoch einfachere Möglichkeiten, dies zu beheben, anstatt das
git
komplexe Rückgängigmachen zu durchlaufen . Ich würde vermuten, dass die meisten Git-Resets für eine kleine Anzahl von Dateien durchgeführt werden. Wenn Sie bereits VIM verwenden, ist dies möglicherweise die zeiteffizienteste Lösung. Die Einschränkung besteht darin, dass Sie bereitsViM's
Persistent-Undo verwenden müssen, was Sie in beiden Fällen verwenden sollten, da Sie damit die unbegrenzte Anzahl von Änderungen rückgängig machen können.Hier sind die Schritte:
Drücken Sie in vim
:
und geben Sie den Befehl einset undodir
. Wenn Siepersistent undo
in Ihrem eingeschaltet haben.vimrc
, wird ein ähnliches Ergebnis wie angezeigtundodir=~/.vim_runtime/temp_dirs/undodir
.Verwenden Sie
git log
in Ihrem Repo , um das letzte Datum / die letzte Uhrzeit herauszufinden, zu der Sie das letzte Commit durchgeführt habenNavigieren Sie in Ihrer Shell zu Ihrer
undodir
Verwendungcd ~/.vim_runtime/temp_dirs/undodir
.Verwenden Sie diesen Befehl in diesem Verzeichnis, um alle Dateien zu finden, die Sie seit dem letzten Festschreiben geändert haben
find . -newermt "2018-03-20 11:24:44" \! -newermt "2018-03-23" \( -type f -regextype posix-extended -regex '.*' \) \-not -path "*/env/*" -not -path "*/.git/*"
Hier ist "2018-03-20 11:24:44" das Datum und die Uhrzeit des letzten Commits. Wenn das Datum, an dem Sie dies getan haben,
git reset --hard
"2018-03-22" ist, verwenden Sie "2018-03-22" und dann "2018-03-23". Dies ist auf eine Eigenart des Funds zurückzuführen, bei der die untere Grenze inklusive und die obere Grenze exklusiv ist. https://unix.stackexchange.com/a/70404/242983Als nächstes gehen Sie zu jeder der Dateien, öffnen Sie sie in vim und machen Sie eine "frühere 20m". Weitere Details zu "früher" finden Sie unter "h früher". Hier
earlier 20m
bedeutet, dass Sie 20 Minuten zurück zum Status der Datei zurückkehren, vorausgesetzt, Sie haben diegit hard --reset
20 Minuten zurück ausgeführt. Wiederholen Sie dies für alle Dateien, die aus demfind
Befehl ausgespuckt wurden . Ich bin sicher, dass jemand ein Skript schreiben kann, das diese Dinge kombiniert.quelle
Ich verwende IntelliJ und konnte einfach jede Datei durchgehen und Folgendes tun:
Edit -> reload from disk
Zum Glück hatte ich gerade ein
git status
Recht getan, bevor ich meine Arbeitsänderungen ausgelöscht hatte, sodass ich genau wusste, was ich nachladen musste.quelle
Wenn Sie sich an Ihre Dateihierarchie erinnern und die Technik von Mark Longair mit Phil Oakley-Modifikation verwenden, erhalten Sie dramatische Ergebnisse.
Wenn Sie die Dateien mindestens zum Repo hinzugefügt, aber nicht festgeschrieben haben, können Sie sie im Wesentlichen durch interaktive Verwendung wiederherstellen
git show
das Protokoll , das Protokoll überprüfen und die Shell-Umleitung verwenden, um jede Datei zu erstellen (wobei Sie sich Ihren interessierenden Pfad merken).HTH!
quelle