2. témakör · Helyi munka: az első commitok · 10. fejezet
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.
git restore, git clean), és visszaveszed az előkészítést (git restore --staged).--amend), és tudod, miért csak feltöltés előtt.reset három módját (--soft, --mixed, --hard) és a revert közti különbséget.reflog segítségével visszacsinálsz; ugyanezeket megtalálod a GitHub Desktopban.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ás | Desktopban | Kockázat |
|---|---|---|---|
| munkakönyvtár (módosított fájl) | git restore fájl | Discard changes | végleges a módosítás elvész |
| munkakönyvtár (új, követetlen fájl) | git clean -f | Discard changes | végleges |
| előkészítési terület | git restore --staged fájl | pipa kivétele | biztonságos a módosítás megmarad |
| utolsó commit, még nincs feltöltve | git commit --amend · git reset | Amend · Undo | óvatosan átírja a helyi történetet |
| feltöltött (pushed) commit | git revert | Revert changes in commit | biztonságos új commitot készít |
Válaszolj a kérdésekre, és megkapod a helyzetedhez illő parancsot.
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
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).
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.
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).
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ó.
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.
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ód | HEAD (commit) | Előkészítési terület | Munkakönyvtár | Mire jó? |
|---|---|---|---|---|
--soft | visszaáll | marad | marad | a commit(ok) „szétszedése”: minden előkészítve marad, azonnal újra commitolható (pl. több commit összevonása) |
--mixed(alapértelmezett) | visszaáll | visszaáll | marad | a változások megmaradnak a fájlokban, de újra kell válogatni őket |
--hard | visszaáll | visszaáll | visszaáll | mindent eldob a célállapotig; a nem commitolt munka végleg elvész |
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 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ó.
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.
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énetgit 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 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.
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"
HEAD@{n} azt jelenti: ahol a HEAD n lépéssel korábban állt. (A HEAD~n ezzel szemben a commitok láncában lép vissza.)reset --hard vagy restore eldobott, nem hozza vissza.
Ezért is jó gyakran commitolni.Figyelj arra, hol van a változás, és fel van-e már töltve!
restore, új fájlnál törlés). A Desktop a fájlt a Lomtárba teszi.reset --soft HEAD~1).--amend). Feltöltött commitnál figyelmeztet.git revert).reset --mixed).reflog-hoz és a reset --hard-hoz nincs gomb: ezekhez parancssor kell (Repository → Open in …).reset --soft HEAD~1) és Commit → Commit Staged (Amend).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.
⭐ alap · ⭐⭐ haladó · ⭐⭐⭐ kihívás
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.
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.
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!
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.
„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.
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?
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.)
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.
| Fogalom | Jelentés |
|---|---|
git restore fájl | a munkakönyvtár módosításának eldobása (vissza az indexbeli állapotra) |
git restore --staged fájl | az előkészítés visszavonása; a módosítás megmarad |
--source=hivatkozás | a restore egy régebbi commitból hozza a fájlt |
git clean | a követetlen fájlok törlése (-n: próba, -f: törlés, -d: mappák is) |
git commit --amend | az utolsó commit lecserélése egy javítottra (új hash); csak feltöltés előtt |
git reset | az á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ása | meglévő commitok lecserélése vagy eltávolítása (amend, reset); megosztott commitoknál kerülendő |
| reflog | a HEAD mozgásainak helyi naplója; HEAD@{n} = ahol a HEAD n lépéssel korábban állt |
| elárvult commit | egyik ágról sem elérhető commit (pl. reset után); a reflogból még visszahozható |
| Discard · Undo | a GitHub Desktop eldobás (restore/clean) és utolsó-commit-visszavonás (≈ reset --soft) funkciója |
git restore fájl, új fájlok: git clean -n, majd -f. Ez végleges.git restore --staged fájl. Régi fájlváltozat: git restore --source=HEAD~n fájl.git commit --amend (új hash!).git reset: --soft (előkészítve marad), --mixed (a fájlokban marad), --hard (minden eldobva). Csak helyi commitokra!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.