Hur tar man bort "Large Files" från en Git Commit?

Permalänk
Hedersmedlem
Skrivet av SimpLar:

Detta stämmer faktiskt inte, Git som verktyg har rätt rejäla begränsningar för vissa typer av filer. Ett repo kan bli stort av att ha väldigt lång historik och väldigt mycket källkod, vilket är fallet för Linux-kärnan. Men det är Git fortfarande bra på att hantera på grund av att det byggdes för just detta ändamål. Ordagrant, Torvalds (m.fl.) byggde Git för att versionshantera Linux. Men stora filer är något helt annat.

Man brukar säga att stora filer är lite utav en akilleshäl för Git, men i själva verket är akilleshälen binära filer, dvs filer som inte är menade att läsas som klartext. Stora filer tenderar dock att vara just binära, vilket antagligen är varför begreppen används för samma koncept. Med antagandet att TS 100MB stora fil är binär (vilket känns rätt sannolikt) så skulle jag säga att det var helt rimligt för denne att ta bort den ur historiken, särskilt med tanke på att det är ett privat projekt utan andra medverkande. Och jag ska såklart förklara varför.

På grund av att Git lagrar hela innehållet i en fil som en blob och därmed måste skapa en ny blob för minsta lilla ändring så växer repot snabbt om man har en binär fil som man gör ändringar i. En binär fil på 100 MB som du ändrar minsta lilla sak i och sedan committar, ja då har du ett repo som är 200 MB stort.

Läser man kapitlet i Git-boken som nämner lagring av stora källkodsfiler så kan man tro att detta inte är något större problem eftersom Git packar ihop liknande objekt i packfiles och lagrar deltan mellan dessa. Det som tyvärr inte framgår här är att Git från topp till tå är optimerat för att lagra klartext. Så att lagra flera versioner av en 100 MB binär fil är ett ganska stort problem, medan samma sak fö` en 100 MB stor CSV-fil med något dataset inte kommer att få repot att växa på samma sätt på grund av att den är klartext och deltan därmed kan beräknas från en version till en annan.

Vi kan göra ett litet experiment med en snarlik version av exemplet jag hade ovan, där vi committar PDFen som det står "Hej!" i (som till största del är binärt nonsens). PDFen i sig är ca 24KB, och även i komprimerad blob-form är den ca 24KB (den är faktiskt några hundra byte mindre i blobformen i detta fall).

$ ls -l -h total 28K -rw-r--r-- 1 simplar simplar 5 Jul 16 10:33 README.md -rw-r--r-- 1 simplar simplar 24K Jul 16 10:33 README.pdf $ git hash-object README.pdf # <-- to determine object hash to find it in the database 73d3e81c91e7581f984ba50e311cec4b8744689a $ ls -l -h .git/objects/73/d3e81c91e7581f984ba50e311cec4b8744689a -r--r--r-- 1 simplar simplar 24K Jul 16 10:35 .git/objects/73/d3e81c91e7581f984ba50e311cec4b8744689a

Om vi packar denna i en packfile (Git gör detta automatiskt vid vissa tillfällen) så får vi i praktiken samma storlek som blobben, eftersom en "bas" måste sparas i sin helhet.

$ git repack $ ls -l -h .git/objects/pack/ total 32K -r--r--r-- 1 simplar simplar 1.2K Jul 16 10:49 pack-79c806373a2e0fd3f96a4fea204b8bf04bb6d2c3.idx -r--r--r-- 1 simplar simplar 24K Jul 16 10:49 pack-79c806373a2e0fd3f96a4fea204b8bf04bb6d2c3.pack -r--r--r-- 1 simplar simplar 68 Jul 16 10:49 pack-79c806373a2e0fd3f96a4fea204b8bf04bb6d2c3.rev

Om vi nu ändrar något litet, exempelvis ändrar texten från "Hej!" till "Hej" och kompilerar om PDFen kommer den ha nära identisk storlek och innehåll i praktiken. Comittar vi den får vi som sagt en ny blob som också är 24KB, men det intressanta är att packfilen blir dubbelt så stor, vilket i praktiken gör att repot för all framtid kommer vara dubbelt så stort (om vi inte får en ny algoritm för att packa packfiler).

$ ls -l -h total 28K -rw-r--r-- 1 simplar simplar 4 Jul 16 10:58 README.md -rw-r--r-- 1 simplar simplar 24K Jul 16 10:33 README.pdf $ ls -l -h .git/objects/pack/ total 56K -r--r--r-- 1 simplar simplar 1.4K Jul 16 11:00 pack-6c7d064fa855062137a6c6af6039dcbfe88c77da.idx -r--r--r-- 1 simplar simplar 48K Jul 16 11:00 pack-6c7d064fa855062137a6c6af6039dcbfe88c77da.pack -r--r--r-- 1 simplar simplar 92 Jul 16 11:00 pack-6c7d064fa855062137a6c6af6039dcbfe88c77da.rev

Om jag istället tar en godtycklig källkodsfil från Linux-kärnan på ca 38KB och gör samma sak får jag ett helt annat resultat på grund av att den är klartext.

$ git add arraymap.c $ git commit -m 'Add arraymap.c' $ git repack $ ls -l -h .git/objects/pack/ [...] -r--r--r-- 1 simplar simplar 8.8K Jul 16 11:15 pack-a355016827401876bb13400a4a5e084c8d8e6db5.pack $ echo '// hello there' >> arraymap.c $ git commit -am 'Append greeting' $ git repack $ ls -l -h .git/objects/pack/ [...] -r--r--r-- 1 simplar simplar 9.0K Jul 16 11:17 pack-ca725db684ea1735cae3ddf3055b44c09c19d55e.pack [...]

Inte nog med att den initiala packfilen blev betydligt mindre än källfilen på grund av att komprimeringen (som är zlib) faktiskt hade någon effekt, utan den andra packfilen som innehåller två versioner av filen blev bara ett par hundra byte större! Det är precis detta Git är byggt för, versioner av klartextfiler med små skillnader mellan varje version.

Det finns alltså väldigt goda tekniska anledningar till att inte versionshantera stora binära filer med Git. Det är helt enkelt inte byggt för det. Där har vi istället tillägg såsom Git LFS som får göra grovjobbet med att spara datan, medan Git håller koll på var vardera version hör hemma i historiken.

Inget av det du säger motsäger något som jag skrev. Precis som du skriver är inte Git optimalt för att versionshantera stora binära filer, men om det t.ex. är några enstaka bilder som är 1 MB stora som ändras ganska sällan (t.ex. assets för ett spel) så hade många idag resonerat att bekvämligheten att ha dem i samma repo överväger att Git inte är optimalt utformat för att hantera binär data. Däremot kanske inte för 20 år sedan då hårddiskar var betydligt mindre. Och i framtiden så kommer också större binära filer accepteras i Git, eftersom de inte är stora nog för att ställa till ett problem.

Det är en tradeoff, diskutrymme mot smidighet. Och den tradeoffen kommer alltid se olika ut för olika personer och projekt, och den lagringsteknik som är tillgänglig vid tillfället.

Permalänk
Medlem
Skrivet av pv2b:

Inget av det du säger motsäger något som jag skrev. Precis som du skriver är inte Git optimalt för att versionshantera stora binära filer, men om det t.ex. är några enstaka bilder som är 1 MB stora som ändras ganska sällan (t.ex. assets för ett spel) så hade många idag resonerat att bekvämligheten att ha dem i samma repo överväger att Git inte är optimalt utformat för att hantera binär data. Däremot kanske inte för 20 år sedan då hårddiskar var betydligt mindre. Och i framtiden så kommer också större binära filer accepteras i Git, eftersom de inte är stora nog för att ställa till ett problem.

Jag skulle säga att det motsäger hela ditt resonemang kring att Git haterar stora filer bra (eller "bör inte ha några åsikter"). Så är inte fallet om filen är binär, Git hanterar binära filer mycket dåligt både vad gäller lagringsutrymme och prestanda för repot i sin helhet. Egentligen är så inte fallet även om filen är i klartext, det kommer också tanka prestandan (dock inte lagringsutrymmet på samma sätt).

Dessutom gällde ämnet stora binära filer, där det initialt handlade om >100 MB. Ditt exempel här ställer in nya kriterier både vad gäller storleken på filen samt att den ändras sällan. Är det möjligt att man skulle kunna göra bedömningen att en liten binär fil sällan eller aldrig kommer ändras och därför kan ligga i repot? Visst. Men det är ett undantag. Den generella tumregeln är att inte versionera binära filer i Git för att det helt enkelt är ett undermåligt verktyg för det.

Skrivet av pv2b:

Det är en tradeoff, diskutrymme mot smidighet. Och den tradeoffen kommer alltid se olika ut för olika personer och projekt, och den lagringsteknik som är tillgänglig vid tillfället.

Det är inte bara diskutrymme som tar en smäll, utan även repots prestanda tar en ordentlig smäll när det finns stora (särskilt binära) filer, särskilt vad gäller synkronisering mellan olika repos (fetch/push). Det är viktigt att förstå att det inte bara handlar om några MB extra på disken. Jag inser dock nu att mitt inlägg antagligen förstärkte uppfattningen att det handlade enbart om just lagringsutrymme, eftersom jag fokuserade på just svårigheten att packa ihop binära filer.

Min poäng är helt enkelt följande. Du kan välja att använda ett verktyg (Git) till något det inte är designat för (lagra stora och binära filer). Men du bör göra det med full förståelse för vad du ger dig in på, vilket någon som inte riktigt förstår Git helt enkelt inte gör och bör därmed inte ges uppfattningen att "det går bra".

Permalänk
Medlem
Skrivet av heretic16:

Nej. Github är absolut inte min felaktiga tjänst. Jag använder molnet för att visa andra mina projekt.
Jag tycker att Git borde ge en förfrågan "Vill du inkludera denna fil som är över 100 mb?", innan man inkluderar den. Jag menar, hur svårt ska det vara för Git att ha en sådan förfrågan?

Dom som skapade Git verkar kunna mycket. Men dom glömde bort funktioner som Github rekommenderar...från tredje part. Alltså betyder det att Git har missat några viktiga saker.

Man ska inte behöva ladda ned "trix & fix" för att dra tillbaka en commit som har ej blivit "push".

Det finns ingen 'skall' när man använder sig av tjänster som är gratis eller byggs kring opensource.

Är man inte nöjd med funktioner så får man själv bidra med förbättring och helst bjuda tillbaka källkoden på detta, och är det tillräckligt många som tycker samma sak så kanske det går in i main-line. Det är så hela opensource-världen är byggd.

Du hittade för övrigt lösningar på detta ändå för att andra hade stött på samma problem och faktiskt skapat kod/metoder som löser det. Sedan finns en filosofisk fråga i och med hur GIT är strukturerad om det är rätt att göra så eller inte - men detta är en annan disskussion.

---

GIT är inte Github - men utan GIT skulle Github inte existera och Github är en av många och förvisso bland dom största företagen, som växt kring GIT och gjort den mer 'användarvänlig'

GIT:s uppkomst är baserad på en rad tillfälligheter pga. någons (Andrew Tridgell) nyfikenhet och ett scriptsnurra som förenklar jobbet för hans del - en grinig CEO (Larry McVoy) på Bitkeeper som inte gillade detta och kort därefter en frusterad Linus Torvalds när kopplingen mot bitkeeper klipptes när han skulle administrera Linuxkärnas källkodsträd och sedan är resten som det heter - historia. "https://en.wikipedia.org/wiki/Git" klicka också vidare på "Andrew Tridgell" då han är orsaken till 'att det hände'"

Det är flertal gamla SCM-företag som gått i graven (inklusive Bitkeeper) eller måste remodulera verksamheten att också hantera GIT om de skall överleva - och somliga av dessa var väldigt bortskämda med välbetalande stadiga kunder från myndigheter och stora företag år efter år och så kom GIT och rivde upp det hela med rötterna i hur man hanterar källkod och dess revisions-hantering och också en mångårig uppdämd missnöje från programmerarhåll (inklusive Linus) med dessa SCM-företag gjorde också att processen gick fort i riktning mot GIT.

Permalänk
Medlem
Skrivet av SimpLar:

Inte nog med att den initiala packfilen blev betydligt mindre än källfilen på grund av att komprimeringen (som är zlib) faktiskt hade någon effekt, utan den andra packfilen som innehåller två versioner av filen blev bara ett par hundra byte större! Det är precis detta Git är byggt för, versioner av klartextfiler med små skillnader mellan varje version.

Nu blir jag nyfiken. Vad är skillnaden mellan ”binär” och ”text” från gits perspektiv? För zlib behandlar väl alla tecken ”lika”?

Finns det verkligen någon annan skillnad än att PDF:en är komprimerad från början, dvs bara informationen finns kvar och bruset är bortplockat, till skillnad från i källkoden?

Permalänk
Medlem
Skrivet av KAD:

Nu blir jag nyfiken. Vad är skillnaden mellan ”binär” och ”text” från gits perspektiv? För zlib behandlar väl alla tecken ”lika”?

Finns det verkligen någon annan skillnad än att PDF:en är komprimerad från början, dvs bara informationen finns kvar och bruset är bortplockat, till skillnad från i källkoden?

Dels så är det ju det faktum att textfiler oftast går att komprimera rätt bra, medan många binär-format redan inkluderar komprimering.

Men viktigare, ur gits synvinkel, är att det på ett vettigt sätt går att göra rad-baserade diffar mellan textfiler.

I princip går det ju att göra en diff mellan två binärfiler också, men resultatet är inte människoläsbart, och för många binära format så kan även en liten ändring i källdata åstadkomma väldigt stora ändringar i binärfilen.

Permalänk
99:e percentilen
Skrivet av pv2b:

Men jag tycker det är en väldigt märklig inställning här i tråden att hoppa på TS. Han har gjort ett misstag, men istället för att visa honom till en lösning så sätter man sig istället på höga hästar och pratar om att "man inte ska göra så", eller att det är "omöjligt". Jag vet inte om det är okunskap eller arrogant. Det är klart att det finns en lösning, och det är klart att det finns nackdelar med denna, men det finns stora nackdelar med att ha ett gitrepo som är för stort också. Vad ska TS göra istället menar ni andra som moraliserar? Börja om på ett nytt repo? Det löser ju inget...

Det är lite som om någon skulle komma in på ett bilforum efter att ha råkat få buckla en panel på bilen och sedan få till svar att "lol lär sig parkera bättre din noob". Det löser liksom inte problemet.

Skrivet av immutable:

Detta är något jag tyvärr märkt i flera trådar på sistone.

Det blir vanligare och vanligare att istället för att hjälpa någon så blir den som råkat göra något galet påhoppad och nästan mobbad istället.

Det är en utveckling jag verkligen inte gillar

Skrivet av SimpLar:

Svaren här känns lite onödigt konfrontativa. TS förstår uppenbarligen inte hur Git fungerar men det är inte särskilt hjälpsamt för någon att konstatera det utan att på något sätt hänvisa till vilken kunskap som saknas. Så här kommer jag med det långa svaret som ingen egentligen bad om, men jag känner behövs.

Om man läser svaren innan era i sin kontext och med antagandet att skribenterna bara menar precis vad de skriver, utan att tolka in mer än vad som står i texten, har jag svårt att se hur man hittar några påhopp, motsvarande "lol noob" eller "nästan mobbning".

Formuleringen "lite onödigt konfrontativa" känns mer välavvägd då, och du har en god poäng i meningen som följer därpå, @SimpLar. Dessutom föregår du ju minst sagt med gott exempel i form av ett otroligt välskrivet inlägg om hur Git fungerar! ⭐️

Med det sagt: om någon som "programmerat i över 12 års tid och är duktig på det" avfärdar en korrekt påpekan om vad GitHub är och inte är med "mitt egna moln där jag slänger upp massa saker som jag kan plocka ned vid behov", så framstår det för mig inte som orimligt att berätta att det är feltänkt, även om man inte förklarar i detalj varför eller lindar in varje ord i bomull och sockervadd. Och nog är det definitivt inte påhopp eller nästan mobbning i varje fall?

Sedan vill jag ge lite ytterligare kontext också.

En faktor som eventuellt skulle kunna ha betydelse i sammanhanget är att TS möjligen av vissa användare skulle kunna anses ha en mångårig historik av att torgföra tämligen bestämda åsikter om allt mellan himmel och jord, föreläsa om hur ditten och datten ska göras, deklarera vilka språk och ramverk som är "bäst" och vilka som är "bluffspråk" eller "beta hipsterspråk", avfärda mångfald bland programmeringsspråk som "religion", envist hävda att det borde vara "enkelt fixat" för en C-kompilator att upptäcka alla fel, och så vidare. Det skulle kunna argumenteras för att det stundtals har suttits på höga hästar, för att låna en formulering av @pv2b.

Säger inte att någon skribent i tråden nödvändigtvis tycker så. Vill bara förtydliga att det inte rör sig om en helt ny medlem som precis skrivit sitt första program, och att det inte är otänkbart att en del användare kan vara lite trötta på vad de eventuellt upplever som en återkommande brist på ödmjukhet och självinsikt.

Visa signatur

Skrivet med hjälp av Better SweClockers

Permalänk
Medlem

Jag kände väl mest att det var uppenbart att TS använde Git till saker som det absolut inte är gjort för och sedan klagade över det. Det rörde sig inte heller om något missförstånd som behövde redas ut utan TS behövde bara skaffa sig lite grundläggande kunskap. Då tycker jag att det räcker fint med att påpeka det eftersom det inte precis är svårt för TS att använda sig av Internet för att läsa på. Visst gjorde @SimpLar en jättefin guide men jag tyckte inte att jag behövde lägga ner den tiden när det redan finns hundratals på nätet.