Die Lösung, die ich vorschlagen möchte, basiert auf verwaisten Zweigen und einem leichten Missbrauch des Tag-Mechanismus, der im Folgenden als * Orphan Tags Binary Storage (OTABS) bezeichnet wird.
TL; DR 12-01-2017 Wenn Sie Githubs LFS oder einen anderen Drittanbieter verwenden können, sollten Sie dies auf jeden Fall tun. Wenn Sie nicht können, dann lesen Sie weiter. Seien Sie gewarnt, diese Lösung ist ein Hack und sollte als solche behandelt werden.
Wünschenswerte Eigenschaften von OTABS
- es ist ein reines git und git nur Lösung - es erledigt die Arbeit ohne Software von Drittanbietern (wie git-annex) oder Infrastruktur von Drittanbietern (wie Githubs LFS).
- Die Binärdateien werden effizient gespeichert , dh der Verlauf Ihres Repositorys wird nicht aufgebläht.
git pull
und git fetch
einschließlich git fetch --all
sind immer noch bandbreiteneffizient , dh nicht alle großen Binärdateien werden standardmäßig von der Fernbedienung abgerufen.
- es funktioniert unter Windows .
- Es speichert alles in einem einzigen Git-Repository .
- Es ermöglicht das Löschen veralteter Binärdateien (im Gegensatz zu bup).
Unerwünschte Eigenschaften von OTABS
- Dies macht
git clone
möglicherweise ineffizient (aber nicht unbedingt, abhängig von Ihrer Verwendung). Wenn Sie diese Lösung bereitstellen, müssen Sie möglicherweise Ihren Kollegen raten, sie git clone -b master --single-branch <url>
anstelle von zu verwenden git clone
. Dies liegt daran, dass git clone standardmäßig buchstäblich das gesamte Repository klont, einschließlich Dinge, für die Sie normalerweise Ihre Bandbreite nicht verschwenden möchten, wie nicht referenzierte Commits. Entnommen aus SO 4811434 .
- Dies macht die
git fetch <remote> --tags
Bandbreite ineffizient, aber nicht unbedingt den Speicher ineffizient. Sie können Ihren Kollegen jederzeit raten, es nicht zu verwenden.
- Sie müssen regelmäßig einen
git gc
Trick anwenden, um Ihr Repository von allen Dateien zu bereinigen, die Sie nicht mehr benötigen.
- es ist nicht so effizient wie bup oder git-bigfiles . Aber es ist jeweils besser für das geeignet, was Sie versuchen, und mehr von der Stange. Es ist wahrscheinlich, dass Sie Probleme mit Hunderttausenden kleiner Dateien oder mit Dateien im Bereich von Gigabyte haben, aber lesen Sie weiter, um dieses Problem zu umgehen.
Hinzufügen der Binärdateien
Bevor Sie beginnen, stellen Sie sicher, dass Sie alle Ihre Änderungen festgeschrieben haben, Ihr Arbeitsbaum auf dem neuesten Stand ist und Ihr Index keine nicht festgeschriebenen Änderungen enthält. Es kann eine gute Idee sein, alle Ihre lokalen Niederlassungen auf Ihre Fernbedienung (Github usw.) zu übertragen, falls eine Katastrophe eintreten sollte.
- Erstellen Sie einen neuen verwaisten Zweig.
git checkout --orphan binaryStuff
wird den Trick machen. Dies erzeugt einen Zweig, der vollständig von jedem anderen Zweig getrennt ist, und das erste Commit, das Sie in diesem Zweig vornehmen, hat kein übergeordnetes Element, wodurch es zu einem Root-Commit wird.
- Bereinigen Sie Ihren Index mit
git rm --cached * .gitignore
.
- Atmen Sie tief ein und löschen Sie den gesamten Arbeitsbaum mit
rm -fr * .gitignore
. Das interne .git
Verzeichnis bleibt unberührt, da der *
Platzhalter nicht mit ihm übereinstimmt.
- Kopieren Sie in Ihre VeryBigBinary.exe oder Ihr VeryHeavyDirectory /.
- Fügen Sie es hinzu und legen Sie es fest.
- Jetzt wird es schwierig - wenn Sie es als Zweig in die Fernbedienung schieben, laden alle Ihre Entwickler es herunter, wenn sie das nächste Mal
git fetch
ihre Verbindung verstopfen. Sie können dies vermeiden, indem Sie ein Tag anstelle eines Zweigs verschieben. Dies kann sich weiterhin auf die Bandbreite und den Dateisystemspeicher Ihres Kollegen auswirken, wenn dieser die Gewohnheit hat zu tippen git fetch <remote> --tags
, aber zur Problemumgehung weiterlesen. Fahre fort undgit tag 1.0.0bin
- Schieben Sie Ihr Waisen-Tag
git push <remote> 1.0.0bin
.
- Damit Sie Ihren Binärzweig niemals versehentlich verschieben, können Sie ihn löschen
git branch -D binaryStuff
. Ihr Commit wird nicht für die Speicherbereinigung markiert, da ein darauf verwaltetes verwaistes Tag 1.0.0bin
ausreicht, um es am Leben zu erhalten.
Auschecken der Binärdatei
- Wie kann ich (oder meine Kollegen) die Datei VeryBigBinary.exe in den aktuellen Arbeitsbaum auschecken lassen? Wenn Ihr aktueller Arbeitszweig zum Beispiel Master ist, können Sie dies einfach tun
git checkout 1.0.0bin -- VeryBigBinary.exe
.
- Dies schlägt fehl, wenn Sie das Orphan-Tag nicht
1.0.0bin
heruntergeladen haben. In diesem Fall müssen Sie dies git fetch <remote> 1.0.0bin
vorher tun .
- Sie können die
VeryBigBinary.exe
in die Ihres Masters einfügen .gitignore
, so dass niemand in Ihrem Team versehentlich die Hauptgeschichte des Projekts mit der Binärdatei verschmutzt.
Vollständiges Löschen der Binärdatei
Wenn Sie VeryBigBinary.exe vollständig aus Ihrem lokalen Repository, Ihrem Remote-Repository und den Repositorys Ihres Kollegen löschen möchten, können Sie einfach:
- Löschen Sie das verwaiste Tag auf der Fernbedienung
git push <remote> :refs/tags/1.0.0bin
- Löschen Sie das verwaiste Tag lokal (löscht alle anderen nicht referenzierten Tags)
git tag -l | xargs git tag -d && git fetch --tags
. Entnommen aus SO 1841341 mit geringfügiger Modifikation.
- Verwenden Sie einen git gc-Trick, um Ihr jetzt nicht referenziertes Commit lokal zu löschen.
git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc "$@"
. Außerdem werden alle anderen nicht referenzierten Commits gelöscht. Entnommen aus SO 1904860
- Wenn möglich, wiederholen Sie den Trick git gc auf der Fernbedienung. Dies ist möglich, wenn Sie Ihr Repository selbst hosten und dies bei einigen Git-Anbietern wie Github oder in bestimmten Unternehmensumgebungen möglicherweise nicht möglich ist. Wenn Sie bei einem Anbieter hosten, der Ihnen keinen SSH-Zugriff auf die Fernbedienung gewährt, lassen Sie es einfach sein. Es ist möglich, dass die Infrastruktur Ihres Providers Ihr nicht referenziertes Commit in seiner eigenen süßen Zeit bereinigt. Wenn Sie sich in einer Unternehmensumgebung befinden, können Sie Ihrer IT raten, etwa einmal pro Woche einen Cron-Job-Müll auszuführen, der Ihre Fernbedienung sammelt. Ob sie dies tun oder nicht, hat keinen Einfluss auf Ihr Team in Bezug auf Bandbreite und Speicherplatz, solange Sie Ihren Kollegen raten, immer
git clone -b master --single-branch <url>
statt git clone
.
- Alle Ihre Kollegen, die veraltete Orphan-Tags entfernen möchten, müssen nur die Schritte 2-3 anwenden.
- Anschließend können Sie die Schritte 1 bis 8 unter Hinzufügen der Binärdateien wiederholen , um ein neues verwaistes Tag zu erstellen
2.0.0bin
. Wenn Sie sich Sorgen machen, dass Ihre Kollegen tippen git fetch <remote> --tags
, können Sie es tatsächlich erneut benennen 1.0.0bin
. Dadurch wird sichergestellt, dass beim nächsten Abrufen aller Tags die alten 1.0.0bin
nicht referenziert und für die nachfolgende Speicherbereinigung markiert werden (mithilfe von Schritt 3). Wenn Sie versuchen, ein Tag auf der Fernbedienung zu überschreiben, müssen Sie Folgendes verwenden -f
:git push -f <remote> <tagname>
Nachwort
OTABS berührt weder Ihren Master noch andere Quellcode- / Entwicklungszweige. Die Commit-Hashes, die gesamte Historie und die geringe Größe dieser Zweige bleiben davon unberührt. Wenn Sie Ihren Quellcode-Verlauf bereits mit Binärdateien aufgebläht haben, müssen Sie ihn als separate Arbeit bereinigen. Dieses Skript könnte nützlich sein.
Bestätigt, um mit git-bash unter Windows zu arbeiten.
Es ist eine gute Idee, eine Reihe von Standard-Trics anzuwenden , um die Speicherung von Binärdateien effizienter zu gestalten. Durch häufiges Ausführen von git gc
(ohne zusätzliche Argumente) optimiert git die zugrunde liegende Speicherung Ihrer Dateien mithilfe von Binärdeltas. Wenn es jedoch unwahrscheinlich ist, dass Ihre Dateien von Commit zu Commit ähnlich bleiben, können Sie binäre Deltas vollständig ausschalten. Da es keinen Sinn macht, bereits komprimierte oder verschlüsselte Dateien wie .zip, .jpg oder .crypt zu komprimieren, können Sie mit git die Komprimierung des zugrunde liegenden Speichers deaktivieren. Leider ist dies eine Alles-oder-Nichts-Einstellung, die sich auch auf Ihren Quellcode auswirkt.
Möglicherweise möchten Sie Teile von OTABS skripten, um eine schnellere Verwendung zu ermöglichen. Insbesondere das Skripting der Schritte 2-3 vom vollständigen Löschen von Binärdateien in einen update
Git-Hook kann dem Git-Abruf eine überzeugende, aber möglicherweise gefährliche Semantik verleihen ("Abrufen und Löschen aller veralteten Dateien ").
Möglicherweise möchten Sie Schritt 4 des vollständigen Löschens von Binärdateien überspringen , um einen vollständigen Verlauf aller Binäränderungen auf der Fernbedienung auf Kosten des Aufblähens des zentralen Repositorys zu erhalten. Lokale Repositories bleiben im Laufe der Zeit schlank.
In der Java-Welt ist es möglich, diese Lösung mit zu kombinieren maven --offline
, um einen reproduzierbaren Offline-Build zu erstellen, der vollständig in Ihrer Versionskontrolle gespeichert ist (mit maven ist dies einfacher als mit gradle). In der Golang-Welt ist es möglich, auf dieser Lösung aufzubauen, um stattdessen Ihren GOPATH zu verwalten go get
. In der Python-Welt ist es möglich, dies mit virtualenv zu kombinieren, um eine eigenständige Entwicklungsumgebung zu erstellen, ohne sich bei jedem Build von Grund auf auf PyPi-Server verlassen zu müssen.
Wenn Ihre Binär - Dateien sehr oft ändern, wie Build - Artefakte, könnte es eine gute Idee , um Skript eine Lösung , die speichert 5 neueste Versionen der Artefakte in den Orphan - Tags sein monday_bin
, tuesday_bin
..., friday_bin
und auch eine Waise Tag für jede Veröffentlichung 1.7.8bin
2.0.0bin
usw. Sie können die weekday_bin
alten Binärdateien täglich drehen und löschen. Auf diese Weise erhalten Sie das Beste aus zwei Welten: Sie behalten den gesamten Verlauf Ihres Quellcodes, aber nur den relevanten Verlauf Ihrer binären Abhängigkeiten. Es ist auch sehr einfach, die Binärdateien für ein bestimmtes Tag abzurufen, ohne den gesamten Quellcode mit seinem gesamten Verlauf abzurufen: git init && git remote add <name> <url> && git fetch <name> <tag>
sollte dies für Sie tun.