Ich habe ein Git-Repository mit vielen Commits, die sich unter keinem bestimmten Zweig befinden. Ich kann git show
sie, aber wenn ich versuche, Zweige aufzulisten, die sie enthalten, wird nichts zurückgemeldet.
Ich dachte, dies ist das Problem mit den baumelnden Commits / Bäumen (als Ergebnis der Verzweigung -D), also habe ich das Repo beschnitten, aber danach sehe ich immer noch dasselbe Verhalten:
$ git fetch origin
$ git fsck --unreachable
$ git fsck
Keine Ausgabe, nichts baumelt (richtig?). Aber das Commit existiert
$ git show 793db7f272ba4bbdd1e32f14410a52a412667042
commit 793db7f272ba4bbdd1e32f14410a52a412667042
Author: ...
und es ist über keinen Zweig als erreichbar
$ git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042
gibt keine Ausgabe.
Wie genau ist der Stand dieses Commits? Wie kann ich alle Commits in einem ähnlichen Status auflisten? Wie kann ich solche Commits löschen?
git
branch
git-dangling
Samer Buna
quelle
quelle
Antworten:
Beachten Sie, dass Commits, auf die in Ihrem Reflog verwiesen wird, als erreichbar gelten.
Pass, um
--no-reflogs
zu überzeugengit fsck
, sie dir zu zeigen.Sobald Ihre Reflog-Einträge abgelaufen sind, werden diese Objekte auch von bereinigt
git gc
.Ablauf wird durch die geregelt
gc.pruneexpire
,gc.reflogexpire
undgc.reflogexpireunreachable
Einstellungen. Vgl.git help config
.Die Standardeinstellungen sind alle recht vernünftig.
quelle
git help glossary
legt fest , dass , wie es ... während seine Definition für „erreichbar“ down diese Weise nicht verengt ist, so dass sie widersprüchlich sind. Witzig - also stimmt das, was ich gesagt habe, tatsächlich mit der Verwirrung ingitglossary
... Es sind jedoch nicht die Konzepte, die verwirrend sind, sondern nur die Terminologie. Der Punkt ist, dass „baumelnde“ Commits solche sind, auf die sonst nichts hinweist. Wäre es hilfreich, wenn ich "Reflogs für ansonsten nicht erreichbare Commits" sage ?master
Siegit commit
sich in einem Zweig befinden , erhalten Sie ein Commit000001
. Dann tust du esgit commit --amend
, was dir ein Commit gibt000002
. Es gibt keine Tags oder Zweige000001
mehr, die darauf verweisen , und Sie können es ohne die--reflog
Option nicht in Ihrem Protokoll sehen , aber wenn Sie möchten, können Sie trotzdem mit darauf zugreifengit checkout 000001
. Die Frage ist nun: Ist000001
ein baumelndes Commit oder ein nicht erreichbares Commit oder keines oder beides?Gehen Sie folgendermaßen vor, um alle baumelnden und aus den Reflogs erreichbaren Commits zu entfernen:
Aber seien Sie sicher, dass dies das ist, was Sie wollen. Ich empfehle Ihnen, die Manpages zu lesen, aber hier ist das Wesentliche:
git gc
Entfernt nicht erreichbare Objekte (Commits, Bäume, Blobs (Dateien)). Ein Objekt ist nicht erreichbar, wenn es nicht Teil des Verlaufs eines Zweigs ist. Eigentlich ist es etwas komplizierter:git gc
macht einige andere Dinge, aber sie sind hier nicht relevant und nicht gefährlich.Nicht erreichbare Objekte, die jünger als zwei Wochen sind, werden nicht entfernt. Daher verwenden wir
--prune=now
"nicht erreichbare Objekte entfernen, die zuvor erstellt wurden".Objekte können auch über das Reflog erreicht werden. Während Zweige die Geschichte eines Projekts aufzeichnen, zeichnen Reflogs die Geschichte dieser Zweige auf. Wenn Sie Änderungen vornehmen, zurücksetzen usw., werden Commits aus dem Zweigverlauf entfernt, aber git behält sie bei, falls Sie feststellen, dass Sie einen Fehler gemacht haben. Reflogs sind eine bequeme Methode, um herauszufinden, welche destruktiven (und anderen) Operationen an einem Zweig (oder HEAD) ausgeführt wurden, und erleichtern so das Rückgängigmachen einer destruktiven Operation.
Wir müssen also auch die Reflogs entfernen, um tatsächlich alles zu entfernen, was von einem Zweig nicht erreichbar ist. Wir tun dies, indem wir
--all
Reflogs ablaufen lassen. Wieder behält git ein bisschen von den Reflogs bei, um Benutzer zu schützen, also müssen wir ihm erneut sagen, dass er dies nicht tun soll :--expire-unreachable=now
.Da ich das Reflog hauptsächlich verwende, um mich von destruktiven Operationen zu erholen, verwende ich normalerweise
--expire=now
stattdessen, wodurch die Reflogs vollständig gezappt werden.quelle
git reflog expire --expire-unreachable=now --all
lässt alle deine Verstecke fallen!Ich hatte das gleiche Problem, nachdem ich alle Ratschläge in diesem Thread befolgt hatte:
Wenn es kein Reflog und kein Zweig ist, ... muss es ein Tag sein !
Ich entfernte die Tags mit
git tag -d <tagname>
und überarbeitete die Bereinigung, und die alten Commits waren weg.quelle
muss wohl nur sein
auch über Filialen von Fernbedienungen zu berichten
quelle
git push -d origin next
hilft nicht.git fetch --prune
hat den Trick gemacht. In allen Antworten fehlt jedoch eine Überprüfung auf Tags, die auf dieses Commit verweisen. Ich weiß immer noch nicht, wie ich mit einem Commit nach Tags suchen soll (ich habe alle entfernt).git fsck --unreachable
tatsächlich über das Netzwerk mit dem entfernten kommunizieren, um herauszufinden, welche Commits erreichbar sind?git fsck --unreachable
nicht über das Netzwerk mit der Remote kommunizieren, um herauszufinden, welche Remote-Zweige welche Commits enthalten. Die Remote-Zweigstelleninformationen werden lokal gespeichert, z. B. unter.git/refs/remotes/origin
(oder inpacked-refs
).Ich hatte ein ähnliches Problem. Ich lief
git branch --contains <commit>
, und es gab keine Ausgabe wie in der Frage zurück.Aber auch nach dem Laufen
Mein Commit war immer noch zugänglich mit
git show <commit>
. Dies lag daran, dass eines der Commits in seinem abgetrennten / baumelnden "Zweig" markiert war. Ich entfernte das Tag, führte die obigen Befehle erneut aus und war golden.git show <commit>
zurückgegebenfatal: bad object <commit>
- genau das, was ich brauchte. Hoffentlich hilft das jemand anderem, der genauso feststeckte wie ich.quelle
Ich bin versehentlich auf die gleiche Situation gestoßen und habe festgestellt, dass meine Stashes Verweise auf das nicht erreichbare Commit enthalten. Daher war das vermutete nicht erreichbare Commit über Stashes erreichbar.
Dies war, was ich getan habe, um es wirklich unerreichbar zu machen.
quelle
git gc --prune=<date>
Standardmäßig werden Objekte beschnitten, die älter als zwei Wochen sind. Sie können ein neueres Datum festlegen. Bei git-Befehlen, die lose Objekte erstellen, wird jedoch im Allgemeinen git gc --auto ausgeführt (wodurch lose Objekte beschnitten werden, wenn ihre Anzahl den Wert der Konfigurationsvariablen gc.auto überschreitet).Sind Sie sicher, dass Sie diese Commits löschen möchten? Die Standardeinstellung von gc.auto stellt sicher, dass die losen Objekte nicht unangemessen viel Speicherplatz beanspruchen. Das Speichern loser Objekte für einige Zeit ist im Allgemeinen eine gute Idee. Auf diese Weise können Sie es wiederherstellen, wenn Sie morgen feststellen, dass Ihr gelöschter Zweig ein von Ihnen benötigtes Commit enthält.
quelle