2016-05-09 3 views
0

Motivation: Ich habe ein etwas spezifisches Szenario, für das Git gut zu passen scheint, aber dennoch ungewöhnlich genug ist, um eine bestimmte Arbeit zu erfordern. Im Grunde sind es eine Reihe von Textdateien (kein Code), die mindestens alle 10 Sekunden automatisch aktualisiert werden. Die Änderungen können erheblich sein, und zumindest im Laufe der Zeit wird die Größe des Repositorys relativ groß. Das lokale Repository befindet sich auf einem eingebetteten System ohne ständige Netzwerkkonnektivität. Daher besteht der natürliche Arbeitsablauf darin, die Commits lokal zu erfassen, sie bei einer Opportunity zu verschieben und dann zu löschen, was gerade verschoben wurde, um Speicherplatz freizugeben, falls erforderlich. Der Verlauf kann nützlich sein, um das Gerät vorübergehend zu verwenden, aber vor allem sollte es möglich sein, es vom Gerät zu entfernen. (Es wird für immer auf der Fernbedienung gehalten). Abhängig von einigen anwendungsspezifischen Faktoren kann das Szenario etwas erweitert werden, und wir können zusätzliche Funktionen in git nutzen, aber die Grundstruktur, die ich skizziert habe, sollte gleich bleiben.Git: 'Permanente Löschung' (einer Verzweigung) ohne Umbenennung oder Filterverzweigung

Genauer gesagt gibt es eine lokale Kopie des Repository und eine Fernbedienung, und die lokale nur immer (eine bestimmte Branche) an die Fernbedienung (nie zieht). Das Commit-Diagramm ist einfach, eine "gerade Linie", die nacheinander ohne Verschmelzung oder parallele Linien gebunden wird. Wann immer es die Möglichkeit gibt (wie oben beschrieben) zu pushen, wird ein neuer Zweig für weitere Commits erstellt. Daher haben wir ab und zu einen neuen Zweig, der im Grunde nur dazu dient, die Zeitleiste der Commits zu organisieren. Abgesehen davon wechseln wir nie die Filialen.

So können die alten Zweige entfernt werden, und wie besprochen, ist dies unser Ziel, besonders wenn Platz ein Problem wird. Um ‚dauerhaft zu löschen‘, um die Commits und den Zweig haben wir versucht, die folgenden:

 
date=$(date +"%m-%d-%y--%H-%M-%S") 

git $opt checkout -b "$date" 

git $opt branch -d $to_push 

# the first commit will be the single 'initial' commit in the master 
# branch, which is permanent and never 'deleted' 
git $opt replace --graft \ 
    $(git $opt log -n 1 --pretty="%H") \ 
    $(git $opt rev-list --max-parents=0 HEAD) 

git $opt reflog expire --expire=now --all 
git $opt gc --aggressive --prune=now 
git $opt repack -a -d -l 

Die Opt-Variable wird die Angabe nur die Arbeit Baum und git Richt. Das Graft, das wir ausführen (mit dem nachfolgenden gc etc), beseitigt erfolgreich die Commits von einem naiven git log, und tatsächlich gibt es etwas Platz frei, aber es scheint nicht den Raum frei zu machen, der von den Diffs belegt wird, die noch in den Commits gehalten werden. ; Beispielsweise wird eine große Datei, die erstellt, festgeschrieben und dann gelöscht wird, weiterhin Speicherplatz belegen, nachdem ihre Commits auf diese Weise beseitigt wurden. Wir werden in der Praxis keine besonders großen Dateien haben, aber ich nehme an, dass dieses Verhalten allgemeiner ist, weil die "Daten aus den Änderungen" (diffs?) Immer noch im Repository aufbewahrt werden, oder so ähnlich, was wir tun kümmern sich um die Beseitigung.

Ich schaffte es, die verbleibende Struktur mit einigen Tricks, die mir vorgeschlagen wurden, wie Entfernen der Zweige von der "Fetch" -Klumpen in der Konfiguration und Lauf git fetch --prune origin; und git update-ref -d refs/remotes/origin/05-07-16--15-48-59 zum Beispiel, aber dies hat den fraglichen Raum nicht frei. Die folgenden Daten beschreibt den Zustand des Repository, wie es derzeit steht:

 
$ git log --all --oneline --graph --decorate 
* de345b6 (HEAD -> 05-07-16--15-50-56, replaced) sam. mai 7 15:44:16 EDT 2016 
| * 50272b5 sam. mai 7 15:44:16 EDT 2016 
|/ 
| * 0b96272 sam. mai 7 15:29:48 EDT 2016 
|/ 
| * b764118 sam. mai 7 15:28:13 EDT 2016 
|/ 
| * efa0536 sam. mai 7 15:14:45 EDT 2016 
|/ 
| * 40c8806 sam. mai 7 15:13:57 EDT 2016 
|/ 
| * 6f7c2f9 sam. mai 7 15:12:26 EDT 2016 
|/ 
| * fa33771 sam. mai 7 15:11:21 EDT 2016 
|/ 
| * 8698acd sam. mai 7 15:11:08 EDT 2016 
|/ 
* b2d9486 (origin/master, master) initial 
 
$ git show-ref 
de345b670e24ac68bbbf4aa7efd22598ef3c7251 refs/heads/05-07-16--15-50-56 
b2d9486d5d427d1ae4bb88828f334454a2fb6954 refs/heads/master 
b2d9486d5d427d1ae4bb88828f334454a2fb6954 refs/remotes/origin/master 
0b96272e47cab0b29e2706cae83b8154f8e412ea refs/replace/0afdaca4e6d071fc026d209249a7b0532c11122a 
b7641184c898ff08917d363435d5f45e5e9664ed refs/replace/498f8846c6a742f96997b599f5e25f5ad20b568c 
6f7c2f9b7700b39b4fd837c34ab7911a08d5438a refs/replace/4df4f9cf8cc01500c800f3f04cbbd655a866c9ba 
8698acd667d406fab764389b87518d133de887a6 refs/replace/9a91b7248da808a9fc6e1531c4206a6865273005 
40c880617db664cb73390d90e1401a049bc8c303 refs/replace/9edc1e243f4f36034a800c566fdeeac511e077a3 
efa0536a40e68d92751193fa0c6dec502d77ce72 refs/replace/d6256dbe48a10461e17ca3cf7e7c40700937d249 
fa3377117750fd81c703519038268fec89b65dce refs/replace/db9923391013d8e5d2974f328037f6315af85783 
50272b55f66b8d7c55305a3502db8e9f88b2db03 refs/replace/de345b670e24ac68bbbf4aa7efd22598ef3c7251 

In Bezug auf die Kriterien in diesem Thema erwähnt, wollen wir nicht eine rebase oder filter-branch, weil die Daten in der Arbeit Baum zu tun ist, leben und werden häufig aktualisiert, wie besprochen. Ich nehme an, wir könnten den Arbeitsbaum woanders kopieren und dann die Löschung dort durchführen, aber das verschärft die Platzbeschränkung sogar noch mehr. Und selbst wenn wir es an anderer Stelle kopieren und alte Daten erfolgreich mit Rebase oder Filter-Branch löschen würden, müssten wir alle neuen Änderungen im Live-Repository auf die kopierte übertragen und die kopierte zurück in die Live-Datei kopieren atomar in Bezug auf die Prozesse, die aktiv von den Inhalten des Repositorys lesen und/oder modifizieren, was wie unnötiger Ärger erscheint, aber wir sind offen dafür.

Ein anderer Vorschlag, den wir erhielten, war die Verwendung von format-patch und am, um die Commits zu "serialisieren" und die Struktur im Remote-Repository nach der Übertragung in Form von Textdatei-Patches zu rekonstruieren. Dann könnten wir einfach ein neues Repository auf dem lokalen erstellen, um die alten Daten loszuwerden. Das klingt aber auch unnötig komplex und scheint im Grunde die Arbeit, für die git entwickelt wurde, zu wiederholen. Wir sind offen für diese Möglichkeit (oder die Möglichkeit, zu einem anderen VCS zu wechseln, oder etwas Brauchbares), aber es scheint, als ob wir quälend nah dran sind, das zum Laufen zu bringen, und Git scheint ansonsten ziemlich gut zu unserem Anwendungsfall zu passen.

Ich kann mehr Details zur Verfügung stellen, und ich kann auch das Repository neu erstellen und verschiedene Schritte ausprobieren und/oder Befehlsausgabe bei verschiedenen Schritten im Prozess anzeigen. Vielen Dank für Ihre Zeit.

bearbeiten

Nach dem Vorschlag von Vampir und seine Bitte um weitere Informationen:

 
$ git rev-list --all | xargs -l $git describe --all --always    
replace/de345b670e24ac68bbbf4aa7efd22598ef3c7251 
replace/0afdaca4e6d071fc026d209249a7b0532c11122a 
replace/498f8846c6a742f96997b599f5e25f5ad20b568c 
replace/d6256dbe48a10461e17ca3cf7e7c40700937d249 
replace/9edc1e243f4f36034a800c566fdeeac511e077a3 
replace/4df4f9cf8cc01500c800f3f04cbbd655a866c9ba 
replace/db9923391013d8e5d2974f328037f6315af85783 
replace/9a91b7248da808a9fc6e1531c4206a6865273005 
heads/05-07-16--15-50-56 

Antwort

1

Ihr Problem ist, dass Sie git replace verwenden.
git replace macht git so tun, dass ein Commit in Wirklichkeit ein anderes Commit oder wie in Ihrem Fall das Elternteil eines Commit ist das Elternteil eines anderen Commit.
Aber die ursprünglichen Objekte sind immer noch da, sie sind nur logisch für die meisten Git-Befehle ersetzt, aber nicht physisch ersetzt, es sei denn, Sie tun es mit einem rebase oder filter-branch oder ähnlichem.

Aber wenn ich dich nicht falsch war, was du bist wirklich nach einfach ist der folgende:

git reset --soft <initial commit> 
git commit -m "recording current state as the only commit after the initial commit" 

und dann das Umpacken und Sachen auszulöschen den Müll

Sie können sogar Sachen diese beiden Befehle in einem Git-Alias, um sie zu einer atomaren Operation in Git zu machen, soweit ich mich erinnere.

+0

Vielen Dank für Ihre Antwort. Leider scheint dies die Größe des Repositories nicht verringert zu haben, und die späteren Commits erscheinen immer noch in einem "log --all --oneline --graph --decorate". Ich sollte auch bemerken, dass 'git reflog expire --expire = jetzt all'' 'error: all points nowhere!' Gibt, was vorher schon passiert ist und was ich vergessen habe, in meinem Post zu erwähnen (ich füge es hinzu). Wenn Sie der Meinung sind, dass ein bestimmtes Problem mit meinem aktuellen Test-Repository vorliegt, kann ich ein neues erstellen und es dort versuchen. –

+0

Ich glaube, du vermisst '-' vor 'all', also' --all' statt 'all'. Andernfalls verfällt nur der Reflog des Zweiges namens 'all', der nirgendwo hinweist, wie der Fehler vermuten lässt. – Vampire

+0

Oh, tut mir leid, ja, das hätte klar sein müssen. Mit einem Reflog-Ablauf und einem nachfolgenden GC und Repack habe ich die Größe von 120M auf 80M heruntergesetzt. Was könnte diesen zusätzlichen Raum einnehmen? Ich hätte gedacht, es wäre alles oder nichts. –

Verwandte Themen