Wie hat "git pull" meine Hausaufgaben gegessen?

53

Ich fühle mich wie ein Kind im Büro des Direktors, das erklärt, dass der Hund meine Hausaufgaben in der Nacht vor der Fälligkeit gefressen hat, aber ich starre einen verrückten Datenverlust ins Gesicht und kann nicht herausfinden, wie es passiert ist. Ich würde gerne wissen, wie git mein Repository als Ganzes fressen könnte! Ich habe schon oft Mist in die Verpackung gesteckt und es hat nie geblinzelt. Ich habe es verwendet, um ein 20-Gig-Subversion-Repo in 27-Gig-Repos aufzuteilen und das Foo aus ihnen herauszufiltern, um das Durcheinander zu entwirren, und es hat nie ein Byte an mir verloren. Der Reflog ist immer da, auf den man zurückgreifen kann. Diesmal ist der Teppich weg!

Aus meiner Sicht war alles, was ich getan habe, ausgeführt git pullund mein gesamtes lokales Repository wurde zerstört. Ich meine nicht, dass es "die ausgecheckte Version durcheinander gebracht hat" oder "den Zweig, in dem ich war" oder ähnliches. Ich meine, die ganze Sache ist weg .

Hier ist ein Screenshot meines Terminals zum Vorfall:

Vorfall Screenshot

Lassen Sie sich das erklären. Meine Eingabeaufforderung enthält Daten zum aktuellen Git-Repo (mithilfe der vcs_info-Implementierung von prezto), sodass Sie sehen können, wann das Git-Repo verschwunden ist. Der erste Befehl ist normal genug:

  » caleb » jaguar » ~/p/w/incil.info » ◼  zend ★ »
❯❯❯ git co master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

Dort kann man sehen, dass ich im 'zend'-Zweig war und Master ausgecheckt habe. So weit, ist es gut. Sie werden in der Eingabeaufforderung vor meinem nächsten Befehl sehen, dass er erfolgreich die Zweige gewechselt hat:

  » caleb » jaguar » ~/p/w/incil.info » ◼  master ★ »
❯❯❯ git pull
remote: Counting objects: 37, done.
remote: Compressing objects: 100% (37/37), done.
remote: Total 37 (delta 25), reused 0 (delta 0)
Unpacking objects: 100% (37/37), done.
From gitlab.alerque.com:ipk/incil.info
 + 7412a21...eca4d26 master     -> origin/master  (forced update)
   f03fa5d..c8ea00b  devel      -> origin/devel
 + 2af282c...009b8ec verse-spinner -> origin/verse-spinner  (forced update)
First, rewinding head to replay your work on top of it...
>>> elapsed time 11s

Und einfach so ist es weg. Die Markierung für die abgelaufene Zeit wird vor der nächsten Eingabeaufforderung ausgegeben, wenn mehr als 10 Sekunden vergangen sind. Git hat keine Ausgabe ausgegeben, die über die Meldung hinausgeht, dass die Wiedergabe zurückgespult wird. Kein Hinweis darauf, dass es fertig ist.

Die nächste Eingabeaufforderung enthält keine Daten darüber, in welchem ​​Zweig wir uns befinden oder in welchem ​​Zustand sich Git befindet.

Als ich nicht merkte, dass es fehlgeschlagen war, versuchte ich ahnungslos, einen anderen Git-Befehl auszuführen, nur um zu erfahren, dass ich nicht in einem Git-Repo war. Beachten Sie, dass sich die PWD nicht geändert hat:

  » caleb » jaguar » ~/p/w/incil.info »
❯❯❯ git fetch --all
fatal: Not a git repository (or any parent up to mount point /home)
Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).

Danach zeigte ein Blick in die Runde, dass ich mich in einem völlig leeren Verzeichnis befand. Nichts. Kein ".git" -Verzeichnis, nichts. Leeren.

Mein lokaler Git ist bei Version 2.0.2. Hier sind ein paar Kleinigkeiten aus meiner Git-Konfiguration, die relevant sein könnten, um herauszufinden, was passiert ist:

[branch]
        autosetuprebase = always
        rebase = preserve
[pull]
        rebase = true
[rebase]
        autosquash = true
        autostash = true
[alias]
        co = checkout

Ich habe zum Beispiel git pullfestgelegt, dass immer ein Rebase statt eines Merge durchgeführt wird, sodass ein Teil der obigen Ausgabe normal ist.

Ich kann die Daten wiederherstellen. Ich glaube, es gab keine anderen Git-Objekte als unwichtige Verstecke, die nicht in andere Repos verschoben wurden, aber ich würde gerne wissen, was passiert ist .

Ich habe nachgesehen auf:

  • Nachrichten in dmesg oder im systemd-Journal. Nichts, was auch nur aus der Ferne relevant ist.
  • Es gibt keine Hinweise auf einen Laufwerks- oder Dateisystemfehler (LVM + LUKS + EXT4 sehen alle normal aus). Es ist nichts in Fundsachen.
  • Ich habe nichts anderes gelaufen. Es gibt nichts in der Geschichte, das ich oben nicht zeige, und in dieser Zeit wurden keine anderen Terminals verwendet. Es gibt keine rmBefehle, die in der falschen CWD usw. ausgeführt wurden.
  • Das Stöbern in einem anderen Git-Repo in einem anderen Verzeichnis zeigt keine offensichtliche Abnormalität beim Ausführen von git pulls.

Was sollte ich sonst noch suchen?

Caleb
quelle
4
@Patrick Wie ich bereits in der Frage erklärt habe, existiert nein .gitnicht. Nichts macht das - was früher das Git-Stammverzeichnis war, enthält überhaupt nichts.
Caleb
2
@Alexander Die Pull-Operation ist normal (abgesehen davon, dass es sich eher um eine Rebase als um eine Zusammenführung handelt). Die Benachrichtigung über ein erzwungenes Update zeigt an, dass das Repo, von dem ich ziehe, einen Force Push hatte, der es von einer anderen Position zurücksetzte als das lokale Repo, bei dem es zuletzt gesehen wurde. Dies ist normal, da ich aktiv entwickeltes und häufig neu basiertes Material zwischen meinen eigenen Computern synchronisiere und keinen öffentlichen Zweig, den andere Entwickler sehen werden.
Caleb
3
@Caleb Ihre Shell-Eingabeaufforderung enthält eine Git-Verzweigungsangabe, was bedeutet, dass das Bilden von PS1 Git-Befehle enthält, die nicht in Ihrem Protokoll enthalten sind. Sie können grundsätzlich das Bild verändern und die Problemquelle sein. Sie sollten die Frage aktualisieren, die genau beschreibt, wie Ihre Shell-Eingabeaufforderung gebildet wird, welche Befehle ausgeführt werden, um eine aktuelle Verzweigung abzurufen, und darüber nachdenken, wie sie Ihr Repo verderben könnten.
Netch
2
@Caleb Du solltest wirklich auf der Git-Entwicklungs-Mailingliste nachfragen. Sie können es als Fehlerbericht schreiben oder nur informell fragen - es ist sowieso dasselbe. Es gibt Entwickler, die git eindrucksvoll kennen - sie können wahrscheinlich intuitiv erkennen, was hätte passieren können. (Wenn nicht, werden sie die Diskussion nur ruhig verfolgen.) Und sie wissen, ob es vorher passiert ist. (Es gibt die "offizielle" Möglichkeit, Fehler für git zu melden)
Volker Siegel
7
@Wildcard Eigentlich wollte ich eine Antwort darauf zusammenstellen, da ich tatsächlich herausgefunden habe, was passiert ist. Das System war kürzlich aus dem Ruhezustand hochgefahren, und das Netzwerk war tagelang ausgefallen, bevor es in den Ruhezustand gegangen war. Irgendwo in diesem Prozess ließ ich einen Pacman-Prozess laufen, der versuchte, etwas auf dem System zu aktualisieren. Um es kurz zu machen, es stellte sich heraus, dass glibc aktualisiert und die Git-Binärdatei überschrieben wurde. Aufgrund der Art und Weise, wie es sich gabelte, war eine Instanz anders als die andere und sie aßen sich gegenseitig zu Mittag. Das Verzeichnis war wirklich leer (nicht nur appar
Caleb

Antworten:

6

Ja, gitmeine Hausaufgaben gegessen. Alles davon.

ddNach dem Vorfall habe ich ein Image dieser Disk erstellt und später daran herumgespielt. Ich rekonstruiere die Ereignisserie aus den Systemprotokollen und schließe daraus, dass Folgendes passiert ist:

  1. Ein Systemaktualisierungsbefehl ( pacman -Syu) wurde Tage vor diesem Vorfall ausgegeben.
  2. Ein erweiterter Netzwerkausfall bedeutete, dass erneut versucht wurde, Pakete herunterzuladen. Ich war frustriert über den Mangel an Internet und hatte das System in den Ruhezustand versetzt und war ins Bett gegangen.
  3. Tage später wurde das System aufgeweckt und es wurde wieder begonnen, Pakete zu finden und herunterzuladen.
  4. Der Paket-Download wurde irgendwann beendet, kurz bevor ich mit diesem Repository rumgespielt habe.
  5. Die System Glibc Installation wurde nach dem git checkoutund vor dem aktualisiert git pull.
  6. Die gitBinärdatei wurde nach dem git pullStart und vor dem Ende ersetzt.
  7. Und am siebten Tag gitruhte er sich von all seiner Arbeit aus. Und die Welt gelöscht, damit sich auch alle anderen ausruhen mussten.

Ich weiß nicht genau, unter welchen Rennbedingungen dies geschehen ist, aber das Austauschen von Binärdateien mitten in einer Operation ist sicherlich weder eine nette noch eine überprüfbare / wiederholbare Bedingung. Normalerweise wird eine Kopie einer laufenden Binärdatei im Speicher abgelegt, aber es gitist seltsam und etwas an der Art und Weise, wie Versionen von sich selbst erneut erzeugt werden. Ich bin mir sicher, dass dies zu diesem Durcheinander geführt hat. Offensichtlich hätte es sterben sollen, anstatt alles zu zerstören, aber genau das ist passiert.

Caleb
quelle
1
git könnte fehlgeschlagen sein, da git anstelle einer einzelnen Binärdatei verschiedene Befehle verwendet. Ein einfaches git pull ausführt git-fetch, git-rebaseoder git-mergeundgit gc
Ferrybig
2

Möglicherweise, indem der zu löschende Dateipfad nicht definiert wurde.

Ihr Fall hat mich an einen schönen Tag erinnert, als meine hausgemachte remove(path)Methode versuchte, den Stammordner zu entfernen, weil der angegebene Parameter eine leere Zeichenfolge war, die das Betriebssystem (!) Als Stammordner korrigierte.

Dies kann ein ähnlicher Fehler sein. So dass:

  1. Rebase Befehl wollte eine Datei löschen wie remove(project_folder + file_path)(Pseudocode)
  2. Irgendwie file_pathwar zu der Zeit leer.
  3. Befehl als etwas wie ausgewertet remove(project_folder)
Maliayas
quelle
1

Mit etwas Glück können Sie dies mit dem folgenden Befehl beheben:

git reset --hard ORIG_HEAD  

Wenn potenziell gefährliche Änderungen beginnen, speichert git Ihren aktuellen Status in ORIG_HEAD. Mit ihm können Sie eine Zusammenführung oder Neugründung rückgängig machen.

Git-Handbuch: Rückgängigmachen einer Zusammenführung

Routhinator
quelle
4
Ich glaube nicht, dass Sie die ganze Frage gelesen haben. Diese Art der Korrektur kommt überhaupt nicht in Frage, da es keine Git-Metadaten gibt . Für einen solchen Reset sind ein vorhandenes .git-Verzeichnis und einige Objekte erforderlich. Ich habe nichts. Es ist nicht nur ein durcheinandergebrachtes Arbeitsverzeichnis, es ist auch kein Aufbewahrungsort mehr.
Caleb
Ahh, ich entschuldige mich. Das ist sehr ungewöhnlich. Wenn Git Repo weg ist, gibt es vermutlich keine Möglichkeit zur Wiederherstellung, es sei denn, Sie spiegeln Dateien unter Linux und haben die fs-Backups der Dateien. Ich werde meine Antwort löschen, da sie irrelevant ist.
Routhinator
Ja, ich weiß, dass es ein ungewöhnliches Problem ist (und ich habe Backups). Meine Frage hier ist, wie es schief gelaufen ist ... wo nach dem Fehler in git oder meinem Dateisystemtreiber zu suchen ist oder was auch immer sonst dazu beigetragen haben könnte, ein Verzeichnis mitten in einer Operation wie dieser zu essen.
Caleb
Ich bin auch sehr neugierig. Würde es meinen Repos passieren lassen, dass so etwas passiert.
Routhinator
-1

Sieht so aus, als wäre jemand in git push --forcediesem Repo gelaufen , und Sie haben diese Änderungen vorgenommen. Versuchen Sie, das Repo frisch zu klonen, damit Sie wieder in einen sauberen Arbeitszustand gelangen.

conorsch
quelle
1
Durch den erzwungenen Push wurden die letzten Handvoll Commits neu gegründet. Das habe ich nicht runtergezogen (das Arbeitsverzeichnis ist nicht länger ein Arbeitsverzeichnis!) Und selbst wenn es erneut geklont würde, würde es keinen Sinn ergeben.
Caleb
4
Ich glaube nicht, dass Sie jemandes .gitVerzeichnis mit einem erzwungenen Push entfernen können
Grzegorz