Vezérlőpult
10. Változások visszavonása · Helyi munka: az első commitok

2. témakör · Helyi munka: az első commitok · 10. fejezet

Változások visszavonása

A verziókezelés egyik legnagyobb előnye, hogy a hibák visszacsinálhatók. Ehhez azonban tudni kell, hol van a visszavonandó változás: a munkakönyvtárban, az előkészítési területen, egy helyi commitban, vagy már a GitHubon. Ebben a fejezetben megtanulod a restore, a --amend, a reset és a revert használatát, és a mentőövet: a reflog-ot.

CLI + DesktopVisszavonás-varázslóReset-laborSzimulátor15 kvízkérdés

Tanulási célok

1Hol van a változás?

A visszavonás módja attól függ, meddig jutott el a változás. Minél messzebb van, annál több mindenre kell figyelni:

Hol van?VisszavonásDesktopbanKockázat
munkakönyvtár (módosított fájl)git restore fájlDiscard changesvégleges a módosítás elvész
munkakönyvtár (új, követetlen fájl)git clean -fDiscard changesvégleges
előkészítési területgit restore --staged fájlpipa kivételebiztonságos a módosítás megmarad
utolsó commit, még nincs feltöltvegit commit --amend · git resetAmend · Undoóvatosan átírja a helyi történetet
feltöltött (pushed) commitgit revertRevert changes in commitbiztonságos új commitot készít

Visszavonás-varázsló

Válaszolj a kérdésekre, és megkapod a helyzetedhez illő parancsot.

2Módosítás eldobása: restore és clean

Ha egy követett fájlt elrontottál, és vissza akarod állítani a legutóbb előkészített (commitolt) állapotára:

PS> git restore index.html     # egy fájl
PS> git restore .              # minden módosított fájl ebben a mappában és alatta

Az új, még követetlen fájlokat a restore nem érinti, mert a Git nem tud róluk. Ezeket a git clean törli. Mivel a törlés végleges, a Git csak kifejezett kérésre dolgozik:

PS> git clean -n               # próba: mit törölne? (dry run)
Would remove proba.txt
PS> git clean -f               # törlés (-d: a követetlen mappákat is)
Removing proba.txt
⛔ EZT NEM LEHET VISSZACSINÁLNI

A git restore fájl és a git clean -f olyan változást dob el, amely soha nem került a Gitbe, ezért a Git sem tudja visszahozni. Előtte mindig nézd meg a git diff-fel és a git clean -n-nel, mit veszítesz. (A GitHub Desktop Discard changes funkciója a Lomtárba teszi a fájlokat, onnan még előkereshetők.)

Régebbi leírásokban ugyanerre a git checkout -- fájl alakot látod. Ma a git restore az ajánlott, mert a checkout túl sok mindenre való (11. fejezet).

3Az előkészítés visszavonása

Ha véletlenül előkészítettél egy fájlt (pl. egy git add . túl sokat vett fel), kiveheted az előkészítésből. A módosítás megmarad a munkakönyvtárban, csak nem kerül a következő commitba:

PS> git restore --staged config.json
PS> git reset config.json             # régebbi, ugyanazt jelentő alak

Ezt a git status is javasolja: (use "git restore --staged <file>..." to unstage). A Desktopban egyszerűen kiveszed a pipát a fájl mellől.

4Egy régi fájlváltozat visszahozása

Ha egy fájlt egy régebbi commit szerinti állapotára akarsz visszaállítani (a többi fájl és a történet marad), add meg a forrást:

PS> git restore --source=HEAD~3 style.css
PS> git diff                          # ellenőrzés: mi változott?
PS> git commit -am "style.css visszaállítása a korábbi változatra"

A régi tartalom a munkakönyvtárba kerül, mintha kézzel írtad volna vissza. Ha jó, commitold. Ha csak meg akarod nézni, arra a git show HEAD~3:style.css való (8. fejezet).

5Az utolsó commit javítása: --amend

Elírtad az üzenetet, vagy kimaradt egy fájl? A legutolsó commit kijavítható:

# csak az üzenet javítása
PS> git commit --amend -m "feat: kapcsolat oldal"

# kimaradt fájl pótlása, az üzenet marad
PS> git add style.css
PS> git commit --amend --no-edit

Az --amend valójában nem módosítja a régi commitot, hanem egy újat készít helyette, új hash-sel (emlékezz: a hash a tartalomból számolódik, 8. fejezet). A régi commit „félreáll”, a reflogban még megtalálható.

⚠️ CSAK FELTÖLTÉS ELŐTT

Ha a commitot már feltöltötted (push), és valaki letöltötte, az ő gépén a régi hash marad. Az átírt commit feltöltését a GitHub elutasítja, és csak kényszerített feltöltéssel lehetne felülírni, ami a társaidnál gondot okoz (19. fejezet). Feltöltött commitot inkább egy új, javító commit kövessen.

6git reset: a HEAD visszaállítása

A git reset cél az aktuális ág végét (és vele a HEAD-et) egy korábbi commitra állítja. A cél utáni commitok kikerülnek az ág történetéből. A kérdés, hogy a változásaik hová kerülnek. Ezt a mód dönti el:

MódHEAD (commit)Előkészítési területMunkakönyvtárMire jó?
--softvisszaállmaradmarada commit(ok) „szétszedése”: minden előkészítve marad, azonnal újra commitolható (pl. több commit összevonása)
--mixed
(alapértelmezett)
visszaállvisszaállmarada változások megmaradnak a fájlokban, de újra kell válogatni őket
--hardvisszaállvisszaállvisszaállmindent eldob a célállapotig; a nem commitolt munka végleg elvész

Reset-labor: mi hová kerül?

Az etlap.html három commiton át változott (v1 → v2 → v3). Próbáld ki a három módot, és figyeld, melyik terület mit tartalmaz!


    
PS> git reset --soft HEAD~1     # az utolsó commit visszavonása, a változás előkészítve marad
PS> git reset HEAD~2            # = --mixed: két commit vissza, a változások a fájlokban
PS> git reset --hard HEAD       # minden nem commitolt módosítás eldobása (!)
PS> git reset --hard a3f1c07    # vissza egy adott commitra; ami utána jött, lekerül az ágról
⚠️ A RESET ÁTÍRJA A TÖRTÉNETET

A reset utáni commitok eltűnnek az ágról. A saját gépeden ez rendben van, de feltöltött commitokra ne használd: arra a revert való.

7git revert: biztonságos visszavonás

A git revert commit nem töröl semmit a történetből. Készít egy új commitot, amely pontosan az adott commit változásainak ellenkezőjét tartalmazza: amit az hozzáadott, azt törli, amit törölt, azt visszateszi.

Kiinduló helyzetA—B—C (hibás)
git reset --hard HEAD~1A—B—C a C eltűnik az ágról: akinél már megvan, annál ütközik a történet
git revert CA—B—C—C′ Revert "C" a történet csak bővül: mindenkinél gond nélkül frissíthető
PS> git revert c8b4e61
# megnyílik a szerkesztő a kész üzenettel: Revert "style: villogó főcím"
[main 5d2a9e1] Revert "style: villogó főcím"
 1 file changed, 2 deletions(-)
PS> git revert HEAD --no-edit   # a legutolsó commit visszavonása, szerkesztő nélkül
ℹ️ HA A FÁJL AZÓTA TOVÁBB VÁLTOZOTT

Ha a visszavonandó commit óta ugyanazokat a sorokat mások is módosították, a revert ütközést jelez, mert nem tudja, melyik változat legyen a jó. Az ütközések feloldását a 13. fejezetben tanuljuk; addig a git revert --abort mindent visszaállít.

8Mentőöv: a reflog

A Git minden alkalommal feljegyzi, amikor a HEAD elmozdul (commit, amend, reset, revert, később ágváltás). Ez a reflog. Ha egy resettel vagy amenddel „eltüntettél” egy commitot, innen visszahozhatod:

PS> git reflog
9c41e07 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~1
5d2a9e1 HEAD@{1}: revert: Revert "style: villogó főcím"
9c41e07 HEAD@{2}: commit (amend): feat: kapcsolat oldal
b7f03aa HEAD@{3}: commit: feat: kapcsolt oldal
…
PS> git reset --hard HEAD@{1}   # vissza oda, ahol egy lépéssel korábban voltunk
HEAD is now at 5d2a9e1 Revert "style: villogó főcím"

9Melyik parancs kell?

Válaszd ki a helyzethez illő parancsot!

Figyelj arra, hol van a változás, és fel van-e már töltve!

1 / 10Pontszám: 0
…

10A Desktopban és a VS Code-ban

Desktop Changes fül
  • Jobb klikk egy fájlon → Discard changes…: a módosítás eldobása (= restore, új fájlnál törlés). A Desktop a fájlt a Lomtárba teszi.
  • Jobb klikk a lista fejlécén → Discard all changes…: minden módosítás eldobása.
  • A pipa kivétele = az előkészítés visszavonása.
  • Commit után a bal alsó sarokban megjelenik az Undo gomb: visszavonja az utolsó, még fel nem töltött commitot, a változások megmaradnak (≈ reset --soft HEAD~1).
Desktop History fül
  • Jobb klikk a legutolsó commiton → Amend commit…: üzenet javítása, fájl pótlása (= --amend). Feltöltött commitnál figyelmeztet.
  • Jobb klikk bármely commiton → Revert changes in commit (= git revert).
  • Az újabb verziókban: Reset to commit…, amely a változásokat megtartja (≈ reset --mixed).
  • A reflog-hoz és a reset --hard-hoz nincs gomb: ezekhez parancssor kell (Repository → Open in …).
IDE VS Code
  • A Source Control panelen egy fájl fölé víve: ↶ Discard Changes, + Stage, − Unstage Changes.
  • A … menüben: Commit → Undo Last Commit (≈ reset --soft HEAD~1) és Commit → Commit Staged (Amend).
  • A Timeline nézetből egy fájl régi változata megnyitható és visszamásolható.

11Gyakorlás a szimulátorban

A szakkor repóban a robotika szakkör weboldala van. Néhány dolog elromlott: dobd el, javítsd ki, vond vissza! A szimulátor alatt a commitlánc látszik; a resettel „elárvult” commitok szaggatott kerettel jelennek meg.

PowerShell + Git

Windows PowerShell
Küldetések 0 / 9

    12Feladatok

    Gyakorló feladatok

    ⭐ alap · ⭐⭐ haladó · ⭐⭐⭐ kihívás

    10.1⭐CLI

    Egy gyakorló repóban rontsd el egy fájl tartalmát, nézd meg a git diff-et, majd állítsd vissza git restore-ral. Hozz létre két szemétfájlt, és töröld őket git clean -n, majd -f segítségével.

    10.2⭐CLI

    Készíts egy commitot szándékosan elírt üzenettel, és javítsd ki --amend-del! Hasonlítsd össze a commit hash-ét előtte és utána (git log --oneline), és keresd meg mindkettőt a git reflog-ban.

    10.3⭐

    Oldd végig a Visszavonás-varázsló összes ágát, és készíts belőle egy saját, egyoldalas „Mit tegyek, ha…?” puskát!

    10.4⭐⭐CLI

    Készíts három kis commitot, majd git reset --soft HEAD~3 után vond össze őket egyetlen commitba. Nézd meg előtte és utána a git log --oneline kimenetét.

    10.5⭐⭐CLI

    „Veszítsd el” egy commitodat git reset --hard HEAD~1-gyel, majd hozd vissza a reflog segítségével! Írd le a lépéseket és a használt HEAD@{n} hivatkozást.

    10.6⭐⭐Desktop

    A GitHub Desktopban próbáld ki a Discard changes, az Undo, az Amend commit és a Revert changes in commit funkciót! Mindegyik után nézd meg a parancssorban a git log --oneline és a git reflog kimenetét: melyik parancsnak felelt meg?

    10.7⭐⭐⭐CLI

    Egy fájlban három commit módosítsa ugyanazt a sort. Próbáld revert-tel visszavonni a középsőt! Mit tapasztalsz? Vond vissza a próbálkozást a git revert --abort paranccsal, és magyarázd meg, miért nem sikerült. (Előzetes a 13. fejezethez.)

    13Önellenőrző kvíz

    Ellenőrizd magad!

    Az egyválasztós kérdéseknél kattints a válaszra. A többválasztósaknál jelöld be az összes helyeset, majd nyomd meg az Ellenőrzés gombot.

    14Fogalomtár

    FogalomJelentés
    git restore fájla munkakönyvtár módosításának eldobása (vissza az indexbeli állapotra)
    git restore --staged fájlaz előkészítés visszavonása; a módosítás megmarad
    --source=hivatkozása restore egy régebbi commitból hozza a fájlt
    git cleana követetlen fájlok törlése (-n: próba, -f: törlés, -d: mappák is)
    git commit --amendaz utolsó commit lecserélése egy javítottra (új hash); csak feltöltés előtt
    git resetaz ág végének visszaállítása egy korábbi commitra; --soft / --mixed / --hard
    git revertúj commit, amely egy korábbi commit változásait visszafordítja; a történet nem íródik át
    történet átírásameglévő commitok lecserélése vagy eltávolítása (amend, reset); megosztott commitoknál kerülendő
    refloga HEAD mozgásainak helyi naplója; HEAD@{n} = ahol a HEAD n lépéssel korábban állt
    elárvult commitegyik ágról sem elérhető commit (pl. reset után); a reflogból még visszahozható
    Discard · Undoa GitHub Desktop eldobás (restore/clean) és utolsó-commit-visszavonás (≈ reset --soft) funkciója

    15Összegzés

    1. Munkakönyvtár: git restore fájl, új fájlok: git clean -n, majd -f. Ez végleges.
    2. Előkészítés visszavonása: git restore --staged fájl. Régi fájlváltozat: git restore --source=HEAD~n fájl.
    3. Utolsó, még fel nem töltött commit: git commit --amend (új hash!).
    4. git reset: --soft (előkészítve marad), --mixed (a fájlokban marad), --hard (minden eldobva). Csak helyi commitokra!
    5. Feltöltött commit: git revert, mert új commitot készít. Elveszett commit: git reflog + git reset --hard HEAD@{n}.

    Ezzel a helyi munka alapjai megvannak. A következő témakörben jönnek az ágak: párhuzamos fejlesztés, összefésülés és ütközések.