Kezdödik már unalmas lenni, hogy a Git repositoryd klónozása percekig tart? Minden egyes push vagy pull műveletnél úgy érzed, mintha az internet a ’90-es évekbeli betárcsázós modem sebességével működne? Nos, van egy rossz hírem: valószínűleg a Git historyd tele van olyan nagy fájlokkal, amiknek soha nem kellett volna oda kerülniük. Ezek a fájlok, legyenek bár ideiglenes fordítási eredmények, óriási adatbázis-mentések, filmek vagy nagy felbontású képek, jelentősen megnövelik a repository méretét, és lassítják a teljes fejlesztési folyamatot. De ne aggódj, van megoldás! Ebben a cikkben részletesen bemutatjuk, hogyan találhatod meg és távolíthatod el ezeket a kísérteteket a Git historyból, hogy repositoryd ismét karcsú és gyors legyen.
Miért Fontos a Git History Tisztántartása?
A Git egy fantasztikus verziókövető rendszer, de még a legjobb eszköz is hajlamos a „hízásra”, ha nem figyelünk rá. A túlzott méretű repository számos problémát okozhat:
- Repository mérete és tárhely: Minél nagyobb a repository, annál több helyet foglal a lemezen, ami különösen problémás lehet nagy csapatok és sok projekt esetén.
- Klónozási idő: Egy új fejlesztő belépésekor vagy egy új környezet beállításakor a repository klónozása az első lépés. Ha ez percekig, órákig tart, az komolyan rontja a termelékenységet. A lassú klónozási idő frusztráló és időpazarló.
- Hálózati forgalom: Minden egyes klónozás, fetch vagy pull jelentős hálózati forgalmat generál. Nagy fájlok esetén ez gyorsan felmeríti a sávszélesség-használat kérdését, különösen távoli munkavégzés vagy lassabb internetkapcsolat esetén.
- Git műveletek teljesítménye: A Git belső működése is lassabbá válhat. A
git log
,git blame
,git checkout
parancsok mind több időt vehetnek igénybe, ha a repository mérete indokolatlanul nagy. - Backupok és archiválás: A nagyobb repositoryk biztonsági mentése és archiválása is több időt és erőforrást igényel.
Ezek mind elegendő okot szolgáltatnak arra, hogy időről időre felülvizsgáljuk és tisztítsuk a Git historyt.
Hogyan Azonosítsuk a Nagy Fájlokat a Git Repositoryban?
Mielőtt bármit is törölnénk, először meg kell találnunk a bűnösöket. Szerencsére a Git és néhány kiegészítő eszköz segít ebben.
Git Parancsokkal
A Git beépített eszközei is képesek feltárni a legnagyobb fájlokat. A leggyakrabban használt és leghatékonyabb módszer a következő:
git rev-list --all --objects |
git cat-file --batch-check="% (size) % (objectname) % (type) % (rest)" |
sort -rh | head -n 10
Nézzük meg, mit is csinál ez a parancs:
git rev-list --all --objects
: Ez listázza az összes objektumot (fájlokat, könyvtárakat, commitokat) a repository teljes történetében.git cat-file --batch-check="% (size) % (objectname) % (type) % (rest)"
: Ez a parancs beolvassa az előző parancs kimenetét, és minden objektumhoz kiírja annak méretét, SHA-azonosítóját, típusát és nevét.sort -rh
: Rendezési parancs, ami a kimenetet méret szerint, fordított sorrendben rendezi (a legnagyobbakkal kezdve). A-h
opció emberi olvasásra alkalmas formában jeleníti meg a méreteket (pl. 10M, 2G).head -n 10
: Csak az első 10 sort (azaz a 10 legnagyobb fájlt/objektumot) mutatja meg.
Ennek a parancsnak a kimenete valahogy így nézhet ki:
120.3M c427d0a2f4a56a6a9b3d2c1e8f7a6b5c4d3e2f10 blob assets/large_video.mp4
80.5M e538f1b3c2d1a0b9c8d7e6f5a4b3c2d1e0f9a8b7 blob data/backup.zip
55.2M f649g8h7i6j5k4l3m2n1o0p9q8r7s6t5u4v3w2x1 blob src/images/high_res_background.png
...
Ha a repository már tömörítve van (ami automatikusan megtörténik idővel a git gc
futtatásakor), akkor az objektumok nem egyedi fájlokként, hanem „pack” fájlokban tárolódnak. Ebben az esetben a következő parancs is hasznos lehet:
git verify-pack -v .git/objects/pack/*.idx | sort -k 3nr | head -n 10
Ez a parancs közvetlenül a pack fájlokat vizsgálja, és kilistázza a bennük lévő legnagyobb objektumokat. A -k 3nr
opció azt jelenti, hogy a harmadik oszlop (a fájlméret bájtban) alapján rendezzük numerikusan, fordított sorrendben.
Külső Eszközökkel
Léteznek grafikus és parancssori eszközök is, amelyek segítenek vizuálisan vagy részletesebben feltárni a repository méretét:
git-sizer
: Egy Python script, ami elemzi a repositoryt és részletes jelentést ad a méretekről, a legnagyobb fájlokról és a potenciális problémákról. Telepíthető pip-pel:pip install git-sizer
.git-repo-size
: Hasonló eszköz, amely szintén részletes méretanalízist biztosít.
Ezek az eszközök segítenek abban, hogy pontosan megértsd, mi teszi a repositoryt nagyméretűvé, és mely fájlokra érdemes fókuszálnod.
A Történelem Átírásának Kockázatai és Következményei
Mielőtt belevágnánk a fájlok törlésébe, elengedhetetlen, hogy megértsük a történelem átírásának súlyát és következményeit. A Git úgy lett tervezve, hogy a történelem elvileg megváltoztathatatlan legyen. Amikor törlünk egy fájlt a Git historyból, valójában nem töröljük a régi commitokat, hanem új commitokat hozunk létre, amelyek nem tartalmazzák az adott fájlt. Ez azt jelenti, hogy:
- A commit SHA-azonosítók megváltoznak: Minden, amit módosítottunk a történelemben, egy új commit hash-t kap.
- Mindenkinek szinkronizálnia kell: Ez a legkritikusabb pont egy megosztott repository esetén. Miután átírtuk a történelmet, MINDENKI MÁSNAK újra kell klónoznia a repositoryt, vagy alapos rebase/reset műveleteket kell végrehajtania, ami bonyolult és hibalehetőségeket rejt.
- Adatvesztés kockázata: Helytelenül elvégzett művelet esetén elveszíthetjük a korábbi munkát. Ezért a biztonsági mentés létfontosságú!
Ezen okokból kifolyólag a történelem átírását csak a legvégső esetben, a legnagyobb körültekintéssel és előzetes kommunikációval szabad elvégezni. Ideális esetben a csapat többi tagja nem dolgozik a repositoryn, amíg ez a folyamat zajlik!
A Megoldás: Eszközök a Nagy Fájlok Eltávolítására
Most, hogy tudjuk, mit keresünk és megértjük a kockázatokat, nézzük meg, milyen eszközökkel tudjuk ténylegesen eltávolítani a nagy fájlokat a Git historyból.
1. A „DEPREKÁLT”, de Ismert: git filter-branch
Régebben a git filter-branch
volt a Git hivatalos eszköze a történelem átírására. Bár képes elvégezni a feladatot, rendkívül lassú, bonyolult a használata, és sok buktatót rejt. A Git dokumentációja maga is lebeszél róla, és azt javasolja, hogy használjunk modernabb, hatékonyabb alternatívákat. Erősen javasoljuk, hogy NE használd ezt az eszközt, hacsak nincs rá különös okod! A továbbiakban a javasolt, modern eszközökre fókuszálunk.
2. A „MODERN” és Ajánlott: git filter-repo
A git filter-repo
a git filter-branch
utódja, és a Git fejlesztői közösség hivatalosan ezt ajánlja a történelem átírására. Sokkal gyorsabb, biztonságosabb, könnyebben használható és rugalmasabb.
Telepítés
A git filter-repo
egy Python script, így pip-pel telepíthető:
pip install git-filter-repo
Győződj meg róla, hogy a Python és a pip megfelelően be van állítva a rendszereden.
Lépésről lépésre útmutató git filter-repo
használatával
Ez a folyamat kritikus, ezért pontosan kövesd a lépéseket:
- Készíts biztonsági mentést! Ezt nem lehet elégszer hangsúlyozni. Készíts egy másolatot a repositoryról egy másik könyvtárba, vagy egyszerűen archiváld a
.git
mappát. - Hozd létre a repository tiszta másolatát: A
git filter-repo
nem szereti, ha közvetlenül a klónozott repositoryn futtatják, mert az megőrzi a reflog-ot és egyéb referenciákat, amelyek megakadályozhatnák az objektumok tényleges törlését. Ideális esetben klónozz egy bare repositoryt a távoli repositoryról, vagy egy friss klónt, amiből eltávolítod a távoli kapcsolatot.- Ha a jelenlegi working directory-ban vagy:
git clone --mirror /path/to/your/repo /path/to/your/repo_mirror.git cd /path/to/your/repo_mirror.git
VAGY egy friss klónt:
git clone --bare https://github.com/user/repo.git cd repo.git
- Ha a már meglévő klónodon dolgoznál, győződj meg róla, hogy nincs benne semmi, amit nem akarsz véglegesen elveszíteni, majd futtasd:
git remote rm origin
Ezzel megszakítod a kapcsolatot a távoli repositoryval, így nem tudsz véletlenül rossz helyre push-olni.
- Ha a jelenlegi working directory-ban vagy:
- Futtasd a
git filter-repo
parancsot:Íme néhány gyakori példa:
- Egy konkrét nagy fájl eltávolítása a teljes historyból:
git filter-repo --path large_file.zip --invert-paths
Ez a parancs eltávolítja a
large_file.zip
nevű fájlt minden commitból. A--invert-paths
azt jelenti, hogy minden mást megtart, kivéve ezt a fájlt. Ha több fájlt szeretnél megadni, többször is használhatod a--path
paramétert. - Minden
.mp4
fájl eltávolítása a historyból:git filter-repo --path-glob '*.mp4' --invert-paths
A
--path-glob
segítségével glob minták alapján adhatsz meg fájlokat. - Minden fájl eltávolítása, ami nagyobb, mint 10 MB (ez a leggyakoribb):
git filter-repo --strip-blobs-bigger-than 10M
Ez a parancs átfésüli a repository teljes historyját, és töröl minden olyan fájlt (blobt), ami nagyobb, mint 10 megabájt.
- Egy könyvtár eltávolítása (pl.
node_modules
vagy.idea
):git filter-repo --path .idea/ --invert-paths
Vagy ha csak egy specific fájl, ami egy könyvtárban volt, pl
assets/large_video.mp4
:git filter-repo --path assets/large_video.mp4 --invert-paths
- Egy konkrét nagy fájl eltávolítása a teljes historyból:
- Tisztítás és tömörítés: Miután a
git filter-repo
befejezte a munkáját, a Git objektumtár még mindig tartalmazhat referenciákat a régi, nagy fájlokra, amelyek nincsenek már elérhetőek a commit historyban. Ezeket el kell távolítani a repository fizikai méretének csökkentése érdekében:git reflog expire --expire=now --all git gc --prune=now --aggressive
git reflog expire --expire=now --all
: Ez törli az összes reflog bejegyzést, ami referálhat a régi objektumokra.git gc --prune=now --aggressive
: Ez futtatja a Git szemétgyűjtőjét, eltávolítja a nem használt objektumokat, és tömöríti a repositoryt. A--aggressive
opció alaposabb tisztítást végez, de tovább tarthat.
- Kényszerített push a távoli repositoryra: Most, hogy a lokális repositoryd tiszta és karcsú, vissza kell push-olnod a változásokat a távoli szerverre. Mivel a history átíródott, egy normál
git push
sikertelen lesz, mert a szerver nem tudja összevonni a helyi változásokat a távoliakkal. Emiatt kényszerített pushra van szükség:git push --force
VAGY még jobb:
git push --force-with-lease
A
--force-with-lease
biztonságosabb, mert csak akkor engedélyezi a push-t, ha a távoli repository állapota megegyezik azzal, amit utoljára lehívtál. Ez megakadályozza, hogy véletlenül felülírd mások munkáját, ha ők időközben push-oltak a repositoryba. - Kommunikáció a csapattal: EZ A LÉPÉS KRITIKUS! Tájékoztasd a csapat minden tagját, hogy a repository története átíródott, és mindenkinek újra kell klónoznia a repositoryt, vagy alaposabban frissíteni a saját helyi másolatát (pl.
git reset --hard origin/main
, majdgit pull
). A legjobb a repo újraklónozása!
3. Az „EGYSZERŰ” és Gyors: BFG Repo-Cleaner
A BFG Repo-Cleaner egy másik kiváló eszköz, amely kifejezetten a nagy fájlok és adatok eltávolítására lett tervezve a Git historyból. JVM-alapú, rendkívül gyors és egyszerű a használata.
Telepítés
Nincs szükség telepítésre a hagyományos értelemben. Csak töltsd le a JAR fájlt a hivatalos weboldalról (https://rtyley.github.io/bfg-repo-cleaner/
).
Lépésről lépésre útmutató BFG Repo-Cleaner használatával
- Készíts biztonsági mentést! Ugyanaz, mint a
git filter-repo
esetén. - Hozd létre a repository tiszta másolatát: A BFG-t is egy bare repositoryn javasolt futtatni:
git clone --mirror https://github.com/user/repo.git cd repo.git
- Futtasd a BFG parancsot:
Íme néhány gyakori példa:
- Minden
.mp4
fájl eltávolítása (és a cache-ből is):java -jar bfg.jar --delete-files *.mp4 my-repo.git
- Egy konkrét nagy fájl eltávolítása:
java -jar bfg.jar --delete-files large_file.zip my-repo.git
- Minden fájl eltávolítása, ami nagyobb, mint 10 MB:
java -jar bfg.jar --strip-blobs-bigger-than 10M my-repo.git
- Egy könyvtár eltávolítása (pl.
node_modules
):java -jar bfg.jar --delete-folders node_modules my-repo.git
- Minden
- Tisztítás és tömörítés: A BFG futtatása után lépj vissza a repository könyvtárába, majd futtasd a következőket:
git reflog expire --expire=now --all git gc --prune=now --aggressive
- Kényszerített push a távoli repositoryra:
git push --force
Vagy a biztonságosabb:
git push --force-with-lease
- Kommunikáció a csapattal: Ne feledd tájékoztatni mindenkit a változásokról!
Fontos Tanácsok és Legjobb Gyakorlatok
- Mindig kommunikálj: Különösen csapatmunkánál elengedhetetlen, hogy mindenkit tájékoztass a repository történetének átírásáról. Egyeztess velük időpontot, amikor mindenki szüneteltetheti a munkát a repositoryn.
- Készíts biztonsági mentést: Mielőtt bármibe belekezdenél, mindig készíts teljes biztonsági mentést a repositoryról.
- Használj
--force-with-lease
-t a--force
helyett: Ez egy sokkal biztonságosabb módja a kényszerített push-nak, mivel ellenőrzi, hogy a távoli repository nem változott-e az utolsó lehívásod óta. - Tisztítsd meg a cache-t: A
git gc --prune=now --aggressive
kulcsfontosságú lépés a fizikai méret csökkentéséhez. - A
.gitignore
fájl szerepe: A legjobb megelőzés, ha sosem engeded be a nagy és felesleges fájlokat a repositoryba. Használd a.gitignore
fájlt a projekted gyökerében, hogy kizárd a fordítási eredményeket, log fájlokat, ideiglenes fájlokat, nagy médiafájlokat stb. - A jövőbeni megelőzés: Git LFS (Large File Storage): Ha gyakran kell nagy médiafájlokat (képeket, videókat, hangfájlokat) tárolnod a repositorydban, fontold meg a Git LFS használatát. Ez a bővítmény lehetővé teszi, hogy a Git csak egy kis mutatót tároljon a nagyméretű fájlok helyett, a tényleges fájlokat pedig egy különálló tárolóban helyezi el. Ez drasztikusan csökkenti a repository méretét és a klónozási időt.
Konklúzió
A Git history tisztítása, különösen a nagy fájlok eltávolítása, egy alapvető karbantartási feladat, amely jelentősen javíthatja a fejlesztési munkafolyamat sebességét és hatékonyságát. Bár a történelem átírása elsőre ijesztőnek tűnhet, a megfelelő eszközökkel (mint a git filter-repo vagy a BFG Repo-Cleaner) és a fenti óvintézkedések betartásával biztonságosan elvégezhető. Ne feledd a biztonsági mentést és a kommunikációt, és élvezd a karcsú, gyors Git repository előnyeit!
Végezetül, gondolj a jövőre: a .gitignore helyes használata és a Git LFS bevezetése segít megelőzni, hogy a repositoryd valaha is újra elhízzon. Egy tiszta repository, egy boldog fejlesztőcsapat!
Leave a Reply