En feil i hvordan Git beregner forskjellen mellom ulike versjoner av samme fil kan føre til at størrelsen på git-repoer mangedobles. Det kan igjen gå ut over ytelsen, og ikke minst føre til at repoet bruker mye mer diskplass enn nødvendig, skriver DevClass.
I en bloggpost med tittelen "How we shrunk our Javascript monorepo git size by 94%" skriver seniorutvikler i Microsoft Jonathan Creamer om hvordan de opplevde at et stort JavaScript-monorepo (1JS) over tid hadde est ut og nå var på hele 178 GB.
Monorepoet er riktignok på mer enn 20 millioner kodelinjer, og man kunne kanskje forvente at det var stort – men som Creamer skriver:
– Av mange grunner, det er rett og slett for stort. Vi har folk i Europa som ikke en gang klarer å klone repoet på grunn av størrelsen. Spørsmålet er, hvordan skjedde dette?!
«Vi har folk i Europa som ikke en gang klarer å klone repoet på grunn av størrelsen.»
Fikk det ned fra 178 til 5 GB
Creamer skriver at da han først fikk tilgang til repoet for noen år siden, var det bare på én eller to gigabyte. Men etter noen måneder hadde det kommet opp i 4 GB. Uten at noen skjønte helt hvorfor.
Etter en del undersøkelser, fant Creamer og hans kollegaer flere måter å hindre at repoet vokste på. Blant annet begrense størrelsen på checkins i Azure DevOps for å unngå at noen ved en feil sjekker inn store binærfiler.
Den største grunnen til at repoet hadde vokst viste seg imidlertid å skyldes en bug, som Creamer fikk hjelp av Git-bidragsyter og Microsoft-utvikler Derrick Stolee til å avdekke.
Feilen kom av at Git bruker noe gammel "packing-kode" skrevet av selveste Linus Torvalds, for å komprimere en fil før den pusher en diff til Git. Problemet var bare at denne koden kun sjekket de siste 16 tegnene i et filnavn. Siden den ikke fikk med seg hele filstien til filen sammenlignet Git noen ganger filer fra ulike pakker – i dette tilfellet CHANGELOG.md fra to ulike pakker.
Resultatet ble at Git fant store forskjeller mellom hver commit, selv om lite var endret. Stolee har forklart i mer detalj hva som skjer i en e-post til Linux Kernel-mailinglisten.
Kai vil vrake Git-begrep: - Kan skape frykt
Fikk det ned fra 178 til 5 GB
Stolee har sendt inn en pull request for Git som tar i bruk noe han kaller et "path walk API" som skal gjøre det mulig for Git å gruppere objekter etter filsti (path) og på den måten unngå at slike feil oppstår.
I Jonathan Creamers bloggpost skriver han at han etter å ha lagt til denne i Microsofts egen Git-fork forsøkte å klone det digre Microsoft-repoet til sin egen maskin. Deretter kjørte han kommandoen git repack med det nye --path-walk-argumentet bak.
– Helt sprøtt! Det gikk fra 178 GB til 5 GB, skriver Creamer.
Creamer oppfordrer nå alle som jobber i store monorepoer, og som har filer med relativt lange navn til å være oppmerksomme hvis de opplever at repoene deres vokser unormalt. Det gjelder spesielt der filene oppdateres ofte (som for eksempel CHANGELOG.md, i Microsofts tilfelle).