Det stora filproblemet i Git
Traditionellt har vissa företag och institutioner hållit sig borta från Git på grund av ineffektiviteten i stor binär filhantering. Videospelutvecklare och medieföretag måste hantera komplexa strukturer, fullfilmsvideo och ljudfiler av hög kvalitet. Forskningsinstitut måste hålla reda på stora datamängder som kan vara gigabyte eller terabyte. Git har svårt att underhålla dessa stora filer.
För att förstå problemet måste vi ta en titt på hur Git håller reda på filer. Närhelst det finns ett engagemang skapar Git en objektnod med en pekare till sin förälder eller flera föräldrar. Git-datamodellen är känd som den riktade acykliska grafen (DAG). DAG-modellen säkerställer att förhållandet mellan förälder och barn aldrig kan bilda några cykler.
Vi kan inspektera DAG-modellens inre arbete. Här är ett exempel på tre åtaganden i ett arkiv:
$ git log - online2beb263 Åtgärd C: tillagd bild1.jpeg
866178e Åtagande B: lägg till b.Text
d48dd8b Åtgärd A: lägg till en.Text
I åtagande A och B har vi lagt till textfil a.txt och b.Text. Sedan i Commit C lade vi till en bildfil som heter image1.jpeg. Vi kan visualisera DAG enligt följande:
Engagera C Engagera B Engagera A2beb263 -> 866178e -> d48dd8b
Om vi inspekterar det senaste åtagandet med följande kommando:
$ git cat-file -p 2beb263träd 7cc17ba5b041fb227b9ab5534d81bd836183a4e3
förälder 866178e37df64d9f19fa77c00d5ba9d3d4fc68f5
författare Zak H
committer Zak H
Åtgärd C: tillagd bild 1.jpeg
Vi kan se att Commit C (2beb263) har Commit B (866178e) som förälder. Nu om vi inspekterar trädobjektet för Commit C (7cc17ba) kan vi se klumparna (binära stora objekt):
$ git cat-file -p 7cc17ba100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 a.Text
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 b.Text
100644 blob a44a66f9e06a8faf324d3ff3e11c9fa6966bfb56 image1.jpeg
Vi kan kontrollera storleken på bildblobben:
$ git cat-file -s a44a66f9e871680
Git håller reda på förändringarna i denna trädstruktur. Låt oss göra en ändring av bilden1.jpeg och kolla historiken:
$ git log - online2e257db Åtgärd D: modifierad bild1.jpeg
2beb263 Åtgärd C: tillagd bild1.jpeg
866178e Åtagande B: lägg till b.Text
d48dd8b Åtgärd A: lägg till en.Text
Om vi kontrollerar Commit D-objektet (2e257db):
$ git cat-file -p 2e257dbträd 2405fad67610acf0f57b87af36f535c1f4f9ed0d
förälder 2beb263523725e1e8f9d96083140a4a5cd30b651
författare Zak H
committer Zak H
Begå D: modifierad bild 1.jpeg
Och trädet (2405fad) inuti det:
$ git cat-file -p 2405fad100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 a.Text
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 b.Text
100644 blob cb4a0b67280a92412a81c60df36a15150e713095 image1.jpeg
Observera att SHA-1-hash för image1.jpeg har förändrats. Det betyder att det har skapat en ny blob för image1.jpeg. Vi kan kontrollera storleken på den nya klumpen:
$ git cat-file -s cb4a0b61063696
Här är ett sätt att visualisera ovanstående DAG-struktur:
Engagera D Engagera C Engagera B Engagera A| | | |
2e257db -> 2beb263 -> 866178e -> d48dd8b
| | | |
Tree4 Tree3 Tree2 Tree1
| | | |
Blobs Blobs Blobs Blobs
Varje engagemangobjekt behåller sitt eget träd. Klobbar hålls inne i trädet. Git optimerar utrymmet genom att se till att det bara lagrar skillnaderna och använder komprimering för lagring. Men för binära filändringar måste Git lagra hela filer i blobbarna eftersom det är svårt att bestämma skillnaderna. Bild-, video- och ljudfiler är redan komprimerade. Som ett resultat, för varje instans av en modifierad binär fil, slutar trädet med en stor blob.
Låt oss tänka på ett exempel där vi gör flera ändringar av en 100 MB bildfil.
Engagera C -> Engagera B -> Engagera A| | |
Tree3 Tree2 Tree1
| | |
Blob3 Blob2 Blob1
300 MB 200 MB 100 MB
Varje gång vi ändrar filen måste Git skapa en 100 MB blob. Så först efter tre åtaganden är Git-arkivet 300 MB. Du kan se att storleken på Git-arkivet snabbt kan sprängas. Eftersom Git är en distribuerad versionskontroll kommer du att ladda ner hela arkivet till din lokala instans och arbeta mycket med filialer. Så de stora klumparna blir en prestationsflaskhals.
Git LFS löser problemet genom att ersätta blobs med lätta pekfiler (PF) och skapa en mekanism för att lagra blobs någon annanstans.
Engagera C -> Engagera B -> Engagera A| | |
Tree3 Tree2 Tree1
| | |
PF3 PF2 PF1
Lokalt lagrar Git blobarna i Git LFS-cache, och fjärr lagras dem i Git LFS-butiken på GitHub eller BitBucket.
PF1 -> Blob1PF2 -> Blob2
PF3 -> Blob3
Nu när du har att göra med Git-arkivet kommer de lätta PF-filerna att användas för de rutinmässiga operationerna. Blobbarna kommer bara att hämtas ut vid behov. Till exempel, om du checkar ut Commit C, kommer Git LFS att slå upp PF3-pekaren och ladda ner Blob3. Så arbetsförvaret blir smalare och prestandan blir bättre. Du behöver inte oroa dig för pekarfilerna. Git LFS kommer att hantera dem bakom kulisserna.
Installera och köra Git LFS
Det har tidigare gjorts försök att lösa Git-storfilsproblemet. Men Git LFS har lyckats eftersom det är lätt att använda. Du behöver bara installera LFS och berätta för det vilka filer du ska spåra.
Du kan installera Git LFS med följande kommandon:
$ sudo apt-get install software-properties-common$ curl -s https: // packagecloud.io / install / repositories / github / git-lfs / script.deb.sh | sudo bash
$ sudo apt-get install git-lfs
$ git lfs installera
När du har installerat Git LFS kan du spåra de filer du vill ha:
$ git lfs-spår "*.jpeg "Spårning "*.jpeg "
Utdata visar att Git LFS spårar JPEG-filer. När du börjar spåra med LFS hittar du en .gitattributes-fil som har en post som visar de spårade filerna. De .gitattribut-filen använder samma notation som .gitignore-fil. Här är hur innehållet i .gitattribut ser ut:
$ cat .gitattribut*.jpeg filter = lfs diff = lfs sammanfoga = lfs -text
Du kan också hitta vilka filer som spåras med följande kommando:
$ git lfs-spårListar spårade mönster
*.jpeg (.gitattribut)
Om du vill sluta spåra en fil kan du använda följande kommando:
$ git lfs untrack "*.jpeg "Spåra "*.jpeg "
För allmänna Git-operationer behöver du inte oroa dig för LFS. Det tar hand om alla backend-uppgifter automatiskt. När du har konfigurerat Git LFS kan du arbeta på förvaret som alla andra projekt.
Ytterligare studier
För mer avancerade ämnen, titta på följande resurser:
- Flytta Git LFS-arkiv mellan värdar
- Ta bort lokala Git LFS-filer
- Ta bort fjärranslutna Git LFS-filer från servern
- Git LFS webbplats
- Git LFS-dokumentation
Referenser:
- git-lfs.github.com: GitHub repo
- github.com / git-lfs / git-lfs / tree / master / docs: GitHub-dokumentation för Git LFS
- atlasiska.com / git / tutorials / git-lfs: Atlassian Tutorials
- Youtube.com: Vad är Git LFS
- Youtube.com: Tracking Huge Files with Git LFS av Tim Pettersen, Atlassian
- Youtube.com: Hantera stora filer på rätt lagring med Git LFS, YouTube
- Youtube.com: Git Large File Storage - Hur man arbetar med stora filer, YouTube
- askubuntu.com / frågor / 799341: hur man installerar git-lfs-på-ubuntu-16-04
- github.com / git-lfs / git-lfs / blob / master / INSTALLING.md: Installationsguide