4.6 Git history és hibakeresés – git log, blame, bisect
Áttekintő
Gondolj a Git historyre mint egy időgépre: nemcsak azt mutatja meg, mi van a kódban most, hanem azt is, hogyan jutottunk ide – és miért. Ez a tudás az egyik legértékesebb eszközöd, amikor valami hirtelen elromlik, és fogalmad sincs, mióta és ki miatt.
Ez az alfejezet három olyan Git parancsra fókuszál, amelyeket a legtöbb junior sosem tanul meg igazán:
git log– a history olvasása, nem csak görgetésegit blame– ki, mikor és miért változtatott egy sortgit bisect– bináris kereséssel megtalálni, melyik commit rontotta el a dolgot
Mellette megnézzük, hogy a jól megírt commit history hogyan spórolja meg a jövőbeli hibakeresési órákat.
Részletes leírás
git log – nem csak görgetés
A git log alapból egy hosszú, nehezen olvasható listát ad. A legtöbb junior erre nyom egy Ctrl+C-t. De ez a parancs annál sokkal több.
Az olvasható forma:
git log --oneline
Kimenet:
a3f1c2e fix: null pointer hiba a user törlőnél
d82b0f1 feat: email küldés hozzáadva
c14a7d9 refactor: authentication modul szétválasztva
Ez már kezelhető. Egy sor = egy commit = könnyen áttekinthető.
A vizuális history – branching és merge-ek megértéséhez:
git log --oneline --graph --all
Kimenet (részlet):
* b3c9d1f Merge pull request #42 from feature/payments
|\
| * f8a2e10 feat: Stripe integráció
| * 1d4b7c3 fix: payment callback URL javítva
* | 9e2a3f1 fix: login redirect hiba
|/
* 2c7d8b0 feat: user regisztráció
Ez megmutatja a branch-ek életútját. Mikor ágaztak el, mikor kerültek vissza mainre. Ha regressziót keresel, ez a nézet segít behatárolni, melyik ág hozta be a hibát.
Szűrés időre és szerzőre:
# Csak az utolsó 2 hét commitjai
git log --oneline --since="2 weeks ago"
# Egy adott szerző munkái
git log --oneline --author="Kovács Anna"
# Egy adott fájl history-ja
git log --oneline -- src/auth/login.py
Ez utóbbi különösen hasznos: ha egy fájl „megváltozott és nem tudom mióta rosszul működik", a fájl szintű log megmutatja az összes vonatkozó commitot.
Diff a commitban:
git log -p --follow -- src/auth/login.py
A -p flag hozzáadja az egyes commitokhoz a tényleges változtatást. A --follow átkövet fájl-átnevezésen is.
git blame – ki írta ezt a sort?
A neve sötéten hangzik, de a git blame nem bűnbakkeresési eszköz – hanem kontextus-keresési eszköz. Az a célja, hogy megértsd: miért van itt ez a sor, mikor kerülhetett be, és van-e mellette valami releváns commit üzenet.
git blame src/auth/login.py
Kimenet (részlet):
^a3f1c2e (Kovács Anna 2024-03-12 14:23:11 +0100 42) def validate_token(token):
^a3f1c2e (Kovács Anna 2024-03-12 14:23:11 +0100 43) if token is None:
d82b0f1a (Nagy Péter 2024-04-02 09:11:05 +0100 44) raise ValueError("Token nem lehet üres")
^a3f1c2e (Kovács Anna 2024-03-12 14:23:11 +0100 45) return decode_jwt(token)
Minden sorhoz látod: commit hash, szerző neve, dátum, sor száma, sor tartalma.
Mit csinálj ezzel:
- Megtalálod, melyik commit változtatta meg az adott sort
- Megnézed azt a commitot részletesen:
git show d82b0f1a - Olvasod a commit üzenetet – és lehetséges, hogy a MIÉRT ott van leírva
Mikor NEM a git blame a helyes eszköz:
- Ha bűnbakot keresel. („Ő írta, ő a hibás.") A blame a kontextusért van, nem az ujjmutatásért.
- Ha az egész fájl át lett formatálva (whitespace-only commit): az összes sor ugyanazt a commitot mutatja, ami nem informativ.
- Ha a fájlt átmozgatták anélkül, hogy a
-Copciót használták volna a commit-ban: a history megszakad.
git bisect – bináris keresés a hibás commitban
Képzeld el: valaki jelzi, hogy „a fizetési folyamat valahol elromlott az utóbbi 3 hétben". Megnézed a logot: 60 commit van az utóbbi 3 hétből. Melyik törte el?
Kézzel végignézni 60 commitot: szenvedés. A git bisect ezt bináris kereséssel csinálja meg.
Hogyan működik:
A bináris keresés elve: mindig felezd a keresési teret. 60 commitból 6 lépés alatt megtalálod a hibásat (log₂(60) ≈ 6).
Használat lépései:
# 1. Indítsd el a bisect folyamatot
git bisect start
# 2. Jelöld meg, hogy a jelenlegi állapot rossz
git bisect bad
# 3. Jelöld meg az utolsó ismert jó állapotot (pl. 3 hetes commit)
git bisect good a1b2c3d
# → Git automatikusan checkout-ol egy közbülső commitot
# Teszteld: működik-e a fizetési folyamat?
# Ha működik:
git bisect good
# Ha nem működik:
git bisect bad
# → Git újra felezi, checkout-ol, teszteled...
# Néhány lépés után:
# "b7f3a1c is the first bad commit"
# 4. Miután megvan a hibás commit:
git bisect reset # visszaállít az eredeti állapotba
Automatizált bisect:
Ha van teszted, amit lefuttathatsz:
git bisect start
git bisect bad HEAD
git bisect good v1.2.0
git bisect run python -m pytest tests/test_payment.py
A Git automatikusan végigfut a commitokon, lefuttatja a tesztet, és megtalálja a hibás commitot – beavatkozás nélkül.
Mikor éri meg a bisect?
- Sok commit között kell keresni (10+)
- A hiba reprodukálható (le tudod ellenőrizni: jó-e vagy rossz)
- Nem tudod a hibát a logból beazonosítani
Hogyan írj historyt, ami segíti a jövőbeli hibakeresést?
A git log, git blame és git bisect csak annyit ér, amennyit a commit üzenetek. Egy „fix" nevű commit hihetetlen frusztrációt okoz 3 hónap múlva.
A jó commit üzenet a jövőbeli detective munkáját segíti:
Rossz:
fix: javítás
Jó:
fix: token validáció hibás null check javítva
A validate_token() None értékre RuntimeError-t dobott
ValueError helyett, ami elnyelte a logging rendszer.
Fixes #234
A blame+log-barát commit azt mondja el:
- Mit változtattál (és ez legyen a subject-ből érthető)
- Miért változtattál (és ez a body-ba kerül)
- Kapcsolódó ticket vagy issue referencia (ha van)
Ennyi befektetés az íráskor órákat spórol debuggoláskor.
Életszerű példák
1. eset: „Mióta lassabb a betöltés?"
Anna senior fejlesztő jelzi, hogy a dashboard lassabb lett az utóbbi hetek óta. Nincs hibaüzenet, csak lassabb.
Gábor junior nekiáll:
# Melyik commitok érintették a dashboard fájlokat az utóbbi 3 hétben?
git log --oneline --since="3 weeks ago" -- src/dashboard/
# Kimenet:
# f3a1b2c feat: dashboard új szűrők hozzáadva
# 9e2c4d1 refactor: dashboard API hívások átírva
# 2b7a3f0 fix: dashboard betöltési spinner javítva
A refactor: dashboard API hívások átírva gyanús. Megnézi:
git show 9e2c4d1
Látja: az átírásban minden szűrőértékhez külön API hívás lett, míg előtte egy batch hívás volt. N+1 query probléma – commit üzenet nem mondta el a „miért"-et, de a diff egyértelmű.
2. eset: „Ki rakta bele ezt a hardcoded URL-t?"
Kódátvizsgálásnál Béla talál egy sorban hardcoded staging URL-t:
API_BASE = "https://staging.example.com/api"
git blame src/config.py
Kimenet megmutatja: 6 héttel ezelőtt, egy sürgős hotfix commitban került be. A commit üzenet: „hotfix: API hiba ideiglenesen javítva". Az „ideiglenesen" maradt.
Béla megtalálja a commitot, megérti a kontextust, és most már nem kérdőjelezi meg a szerzőt – hanem megírja a proper fix-et és egy TODO ticketet.
3. eset: „Valahol elromlott a belépés, de nem tudjuk mikor"
Péter junior megkapja: „A 2FA belépés valahol elromlott az utóbbi 2 hétben."
git bisect start
git bisect bad HEAD
git bisect good $(git log --oneline --since="2 weeks ago" | tail -1 | cut -d' ' -f1)
# Git checkout-ol egy közbülső commitot
# Péter manuálisan leteszteli a 2FA belépést: hibás → bad
git bisect bad
# Git checkout-ol ismét
# Leteszt: hibás → bad
git bisect bad
# Git checkout-ol ismét
# Leteszt: működik → good
git bisect good
# Git megtalálja:
# "e3f1a2b is the first bad commit"
git show e3f1a2b
Commit üzenet: „feat: session timeout rövidítése". A diff mutatja: a timeout értéket ms-ból s-ba változtatták, de elfelejtették a 2FA token validáció timeoutját is frissíteni. Megvan a hiba.
Tesztfeladatok
1. feladat – Parancs párosítás
Párosítsd a Git parancsot a leírással:
| Parancs | Leírás |
|---|---|
git log --oneline | A) Megmutatja, ki módosított egy adott sort, mikor és melyik commitban |
git log --graph --all | B) Tömörített egysoronkénti history |
git blame | C) Megmutatja a branch-ek elágazását és összeolvadását vizuálisan |
git bisect | D) Bináris kereséssel megtalálja, melyik commit vezette be a hibát |
git log -p -- fájl | E) Egy adott fájl commitjait mutatja a tényleges változtatásokkal |
2. feladat – git log kimenet értelmezése
Az alábbi git log --oneline --graph kimenet alapján válaszolj a kérdésekre:
* c4f2a1b Merge pull request #88 from feature/notifications
|\
| * 9d1e3b2 feat: email értesítések hozzáadva
| * 7a4c0f1 fix: SMTP konfiguráció javítva
* | 3b8f2e1 fix: user profile kép feltöltési hiba
|/
* 1e9a7d3 feat: user profil beállítások
* 0f4b6c8 Initial commit
Kérdések:
- Hány branch-en folyt párhuzamosan a fejlesztés?
- Melyik commit javított egy hibát a main branchen a feature branch fejlesztése közben?
- Melyik commit az SMTP-vel kapcsolatos?
- Mi volt a merge előtti utolsó közös pont (melyik commit volt mindkét branch alapja)?
3. feladat – git blame olvasás
Az alábbi git blame részlet alapján:
^3a1b2c9 (Tóth Bence 2024-01-15 10:22:31 +0100 78) def calculate_discount(price, user):
^3a1b2c9 (Tóth Bence 2024-01-15 10:22:31 +0100 79) if user.is_premium:
f9e2d1a0 (Kiss Réka 2024-03-28 16:45:02 +0100 80) return price * 0.8
^3a1b2c9 (Tóth Bence 2024-01-15 10:22:31 +0100 81) return price
Kérdések:
- Ki és mikor adta hozzá a 80. sort?
- Mi volt az eredeti kedvezmény logika Bence verziójában (ha a 80. sor nem volt ott)?
- Hogyan derítsd ki, mi volt a változtatás oka? Melyik git parancsot futtatnád?
- Ha a 80. sor hibás (pl. rossz diszkont arány), kit kell megkérdezni a kontextusért?
4. feladat – git bisect logika
Egy csapatban 50 commit keletkezett az elmúlt 2 hétben. Valahol egy regresszió csúszott be: a PDF export funkció 404-et ad. A 2 héttel ezelőtti verzió még működött.
Minimum hány bisect lépéssel (good/bad döntéssel) lehet megtalálni a hibás commitot?
A) 5 lépés
B) 6 lépés
C) 7 lépés
D) 25 lépés
Indokold a válaszod!
5. feladat – Commit üzenet értékelés
Értékeld az alábbi commit üzeneteket abból a szempontból: mennyire segítik a jövőbeli hibakeresést git blame és git log során?
A commit:
update stuff
B commit:
fix: session kezelés javítva
C commit:
fix: session lejárat 30 percre állítva (volt: undefined)
A bejelentkezés után a session soha nem járt le, mert a
SESSION_LIFETIME változó nem volt beállítva és az alapértelmezett
érték undefined volt. Ez biztonsági kockázat volt.
Refs: #412
Kérdések:
- Melyik commit üzenet a legkevésbé hasznos
git blameesetén? Miért? - Melyik commit üzenet a leghasznosabb
git bisectután (amikor megtaláltad a hibás commitot)? Miért? - A „B" commit elégséges-e, ha a
git show-ban látható a diff is?
6. feladat – Szituációs döntés
Melyik git parancsot használnád az alábbi szituációkban? (Egy-egy sorban indokold is.)
- Szituáció: Egy tesztfájl egy sora furcsa – nem illeszkedik a körülötte lévő logikához. Meg szeretnéd tudni, mikor és miért kerülhetett be.
- Szituáció: Az alkalmazás prod-on eldobott egy exception-t, ami valahol a login folyamatban van. Tudod, hogy 3 héttel ezelőtt még nem volt. Az utóbbi 3 hétben 40 commit keletkezett, és a hiba reprodukálható.
- Szituáció: Egy új csapattag megkérdezi: „Mikor vezettük be a dark mode funkciót és kik dolgoztak rajta?" A feature branch már be van mergelve.
- Szituáció: Egy fájl törölve lett, de nem tudod, mikor és ki törölte.
7. feladat – History alapú nyomozás
Az alábbi git log --oneline kimenet egy kis projekt utolsó 10 commitját mutatja (legújabbtól régibbig):
f1a2b3c fix: törlés után helyes redirect
e4d5c6b feat: komment szerkesztés hozzáadva
d7e8f9a fix: XSS javítás a komment mezőben
c1b2a3d feat: komment törlés hozzáadva
b4c5d6e feat: komment lista megjelenítés
a7b8c9d feat: komment hozzáadás
9f1e2d3 refactor: user controller szétválasztva
8a2b3c4 fix: user regisztráció email validáció
7d1e2f3 feat: user profil szerkesztés
6c4b5a6 Initial commit: user login és regisztráció
Kérdések:
- Melyik commit vezette be legvalószínűbben a komment törlés regresszióját, ha a redirect hiba a törlés funkció bevezetése óta volt?
- Mit csinálnál, ha a
d7e8f9acommitot meg akarod érteni pontosan (melyik mezőben volt XSS és hogyan lett javítva)? - Ha be akarnád határolni, hogy az XSS hiba mikor és melyik commitban jelent meg, melyik eszközt használnád és miért?
8. feladat – igaz/hamis
Jelöld meg, hogy az állítás igaz vagy hamis, és ha hamis, írj helyes változatot.
- A
git blameelsősorban arra való, hogy megtaláljuk, ki a hibás a bugért. - A
git bisectbináris keresést alkalmaz: 64 commit között 6 lépésben megtalálja a hibásat. - A
git log --oneline -- fájlnévmegmutatja az összes commitot, ami az adott fájlt érintette. - A
git bisect run <parancs>automatikusan végigfuttatja a teszteket és megkeresi a hibás commitot. - A jó commit üzenet csak a „mit" mondja el, a „miért" felesleges és zajt okoz.
- A
git log --graph --allcsak a saját branch-ünk history-ját mutatja.