Det store filproblemet i Git
Tradisjonelt har visse selskaper og institusjoner holdt seg borte fra Git på grunn av ineffektiviteten i stor binær filhåndtering. Videospillutviklere og mediebedrifter må håndtere komplekse teksturer, full-motion-videoer og lydfiler av høy kvalitet. Forskningsinstitutter må holde rede på store datasett som kan være gigabyte eller terabyte. Git har problemer med å vedlikeholde disse store filene.
For å forstå problemet, må vi ta en titt på hvordan Git holder rede på filer. Når det er en forpliktelse, oppretter Git en objektnode med en peker til foreldrene eller flere foreldre. Git-datamodellen er kjent som den dirigerte acykliske grafen (DAG). DAG-modellen sikrer at forholdet mellom foreldre og barn aldri kan danne noen sykluser.
Vi kan inspisere det indre arbeidet til DAG-modellen. Her er et eksempel på tre forpliktelser i et depot:
$ git log --online2beb263 Forplikt C: lagt til bilde 1.jpeg
866178e Forplikt B: legg til b.tekst
d48dd8b Forplikt A: legg til en.tekst
I Forpliktelse A og B la vi til tekstfil a.txt og b.tekst. Så i Commit C la vi til en bildefil som heter image1.jpeg. Vi kan visualisere DAG som følger:
Forplikt C Forplikt B Forplikt A2beb263 -> 866178e -> d48dd8b
Hvis vi inspiserer den siste forpliktelsen med følgende kommando:
$ git cat-file -p 2beb263treet 7cc17ba5b041fb227b9ab5534d81bd836183a4e3
foreldre 866178e37df64d9f19fa77c00d5ba9d3d4fc68f5
forfatter Zak H
committer Zak H
Forplikt C: lagt til bilde 1.jpeg
Vi kan se at Commit C (2beb263) har Commit B (866178e) som overordnet. Nå hvis vi inspiserer treobjektet til Commit C (7cc17ba), kan vi se blobs (binære store objekter):
$ git cat-file -p 7cc17ba100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 a.tekst
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 b.tekst
100644 blob a44a66f9e06a8faf324d3ff3e11c9fa6966bfb56 image1.jpeg
Vi kan sjekke størrelsen på bildeblokken:
$ git cat-file -s a44a66f9e871680
Git holder rede på endringene i denne trestrukturen. La oss gjøre en endring av bildet1.jpeg og sjekk historikken:
$ git log --online2e257db Forplikt D: modifisert bilde 1.jpeg
2beb263 Forplikt C: lagt til bilde 1.jpeg
866178e Forplikt B: legg til b.tekst
d48dd8b Forplikt A: legg til en.tekst
Hvis vi sjekker Commit D-objektet (2e257db):
$ git cat-file -p 2e257dbtreet 2405fad67610acf0f57b87af36f535c1f4f9ed0d
foreldre 2beb263523725e1e8f9d96083140a4a5cd30b651
forfatter Zak H
committer Zak H
Forplikt D: modifisert bilde 1.jpeg
Og treet (2405fad) inni det:
$ git cat-file -p 2405fad100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 a.tekst
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 b.tekst
100644 blob cb4a0b67280a92412a81c60df36a15150e713095 image1.jpeg
Legg merke til at SHA-1-hash for image1.jpeg har endret seg. Det betyr at det har skapt en ny klatt for image1.jpeg. Vi kan sjekke størrelsen på den nye blobben:
$ git cat-file -s cb4a0b61063696
Her er en måte å visualisere DAG-strukturen ovenfor:
Forplikt D Forplikt C Forplikt B Forplikt A| | | |
2e257db -> 2beb263 -> 866178e -> d48dd8b
| | | |
Tree4 Tree3 Tree2 Tree1
| | | |
Blobs Blobs Blobs Blobs
Hvert forpliktende objekt opprettholder sitt eget tre. Blobs holdes inne i det treet. Git optimaliserer plass ved å sørge for at den bare lagrer forskjellene og bruker komprimering for lagring. Men for binære filendringer, må Git lagre hele filer i blobs fordi det er vanskelig å bestemme forskjellene. Dessuten er bilde-, video- og lydfiler allerede komprimert. Som et resultat, for hver forekomst av en modifisert binær fil, ender treet med en stor klatt.
La oss tenke på et eksempel der vi gjør flere endringer i en 100 MB bildefil.
Forplikt C -> Forplikt B -> Forplikt A| | |
Tree3 Tree2 Tree1
| | |
Blob3 Blob2 Blob1
300 MB 200 MB 100 MB
Hver gang vi endrer filen, må Git lage en 100 MB blob. Så først etter tre forpliktelser er Git-arkivet 300 MB. Du kan se at størrelsen på Git-arkivet raskt kan sprenge. Fordi Git er en distribuert versjonskontroll, skal du laste ned hele depotet til din lokale forekomst og jobbe mye med filialer. Så de store klatrene blir en ytelsesflaskehals.
Git LFS løser problemet ved å erstatte blobs med lette pekerfiler (PF) og lage en mekanisme for å lagre blobs andre steder.
Forplikt C -> Forplikt B -> Forplikt A| | |
Tree3 Tree2 Tree1
| | |
PF3 PF2 PF1
Lokalt lagrer Git blobs i Git LFS-hurtigbufferen, og eksternt lagrer den dem i Git LFS-butikken på GitHub eller BitBucket.
PF1 -> Blob1PF2 -> Blob2
PF3 -> Blob3
Nå når du har å gjøre med Git-depotet, vil lette PF-filer brukes til rutinemessige operasjoner. Blodene blir bare hentet når det er nødvendig. Hvis du for eksempel sjekker Commit C, vil Git LFS slå opp PF3-pekeren og laste ned Blob3. Så arbeidsdepotet blir slankere og ytelsen blir bedre. Du trenger ikke å bekymre deg for pekerfilene. Git LFS vil administrere dem bak kulissene.
Installere og kjøre Git LFS
Det har vært tidligere forsøk på å løse Git store filproblemet. Men Git LFS har lyktes fordi den er enkel å bruke. Du må bare installere LFS og fortelle hvilke filer du skal spore.
Du kan installere Git LFS ved hjelp av følgende kommandoer:
$ 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 installere
Når du har installert Git LFS, kan du spore filene du vil ha:
$ git lfs-spor "*.jpeg "Sporing "*.jpeg "
Utgangen viser at Git LFS sporer JPEG-filene. Når du begynner å spore med LFS, vil du finne en .gitattributes-fil som vil ha en oppføring som viser de sporede filene. De .gitattributes-filen bruker samme notasjon som .gitignore-fil. Her er hvordan innholdet i .gitattributter ser ut:
$ katt .gitattributter*.jpeg filter = lfs diff = lfs flette = lfs -tekst
Du kan også finne hvilke filer som spores ved hjelp av følgende kommando:
$ git lfs sporOppføring av sporede mønstre
*.jpeg (.gitattributter)
Hvis du vil slutte å spore en fil, kan du bruke følgende kommando:
$ git lfs untrack "*.jpeg "Sporer "*.jpeg "
For generelle Git-operasjoner trenger du ikke å bekymre deg for LFS. Det tar seg av alle backend-oppgavene automatisk. Når du har satt opp Git LFS, kan du jobbe med depotet som ethvert annet prosjekt.
Videre studier
For mer avanserte emner, se på følgende ressurser:
- Flytter Git LFS-depot mellom verter
- Slette Local Git LFS-filer
- Fjerner eksterne Git LFS-filer fra serveren
- Git LFS-nettsted
- Git LFS-dokumentasjon
Referanser:
- git-lfs.github.com: GitHub repo
- github.no / git-lfs / git-lfs / tree / master / docs: GitHub Documentation for Git LFS
- atlassian.com / git / tutorials / git-lfs: Atlassian Tutorials
- youtube.com: Hva er Git LFS
- youtube.com: Tracking Huge Files with Git LFS av Tim Pettersen, Atlassian
- youtube.com: Administrere store filer på riktig lagring med Git LFS, YouTube
- youtube.com: Git Large File Storage - Hvordan jobbe med store filer, YouTube
- askubuntu.no / spørsmål / 799341: hvordan installeres git-lfs-på-ubuntu-16-04
- github.com / git-lfs / git-lfs / blob / master / INSTALLING.md: Installasjonsveiledning