Git Reset Explained - Hogyan menthetem a napot a Reset paranccsal

Ez ismerősen hangzik? "Segítség! Rossz ágra köteleztem el! ” - Megismétlődött ... Hol van az elkötelezettségem?

Nos, annyiszor jártam ott. Valaki segítségül hívja a nevemet, ha valami nem sikerül git. És nemcsak akkor történt, amikor tanítottam diákokat, hanem tapasztalt fejlesztőkkel is.

Az idő múlásával én lettem a „Git srác”.

Folyamatosan használjuk git, és általában ez segíti a munkát. De néha, és sokkal gyakrabban, mint szeretnénk, a dolgok rosszul alakulnak.

Talán rossz ágra köteleztük el magunkat. Talán elvesztettünk egy kódot, amit írtunk. Talán elkövettünk valamit, amire nem gondoltunk.

Számos online erőforrás létezik, amelyek közül gitnéhány (például ez) valójában arra összpontosít, hogy mi történik ezekben a nem kívánt forgatókönyvekben.

De mindig úgy éreztem, hogy ezekből az erőforrásokból hiányzik a „ miért”. Ha parancssorozattal rendelkezik, mit csinálnak az egyes parancsok? És hogyan jutott el eleve ezekhez a parancsokhoz? ?

Egy korábbi bejegyzésemben vizuális bevezetőt nyújtottam a Git belső részlegének. Bár a belső gitelem megértése hasznos, az elmélet megszerzése szinte soha nem elég. Hogyan alkalmazzuk a gitbelsõ ismereteinket, és hogyan használhatjuk azokat a problémák megoldására, amelyekbe belekerültünk?

Ebben a bejegyzésben szeretném áthidalni ezt a szakadékot, és részletezni a git resetparancsot. Megismerjük, mi git resettörténik a kulisszák mögött, majd ezeket az ismereteket felhasználjuk különböző forgatókönyvek megoldására. ?

Gyakori okok - működő dir, index és tár

A belső mechanizmusok megértése érdekében git resetfontos megérteni a belüli változások rögzítésének folyamatát git . Pontosabban a működő dir-t , az indexet és a tárat értem .

Ha bízik ezekben a feltételekben, nyugodtan ugorjon a következő szakaszra. Ha még mélyebb magyarázatot szeretne, tekintse meg ezt az előző bejegyzést.

Amikor a forráskódunkon dolgozunk, akkor egy működő könyvtárból dolgozunk -  a fájlrendszerünk bármelyik könyvtárából, amelyhez tároló van társítva. Ez tartalmazza a projekt mappáit és fájljait, valamint egy könyvtárat .git.

Miután végrehajtottunk néhány módosítást, rögzíteni akarjuk azokat a tárunkban . A tároló ( repo rövid) gyűjteménye vállalkozik , amelyek mindegyike egy archív, amit a projekt munka fa nézett ki, mint egy múltbeli dátum, akár a gép, vagy valaki másé.

Hozzunk létre egy fájlt a működő könyvtárban, és futtassuk git status:

Mégis, gitnem hajt végre változtatásokat a működő fáról közvetlenül az adattárba .

Ehelyett a változásokat először egy indexben vagy az átmeneti területen regisztrálják . Mindkét kifejezés ugyanarra utal, és gyakran használják őket a gitdokumentációban. Ezeket a kifejezéseket felváltva fogjuk használni ebben a bejegyzésben.

Használatkor git addfájlokat (vagy fájlokon belüli változtatásokat) adunk az átmeneti területhez . Használjuk ezt a parancsot a korábban létrehozott fájlon:

Mint git statuskiderül, az aktánk szakaszos (és készen áll az „elkötelezettségre”). Mégis, ez nem része semmilyen elkötelezettségnek . Más szavakkal, ez most a munkafüzetben , valamint az indexben van , de nem a tárban .

Ezután, amikor használjuk git commit, létrehozunk egy kötelezettségvállalást az index állapota alapján . Tehát az új kötelezettségvállalás (az alábbi példában a 3. kötelezettségvállalás) magában foglalja az indexhez előzetesen hozzáadott fájlt.

Más szavakkal, a működő dirnek pontosan ugyanaz az állapota, mint az indexnek és a tárnak .

A parancs git commitemellett az aktuális elágazási masterpontra mutat az újonnan létrehozott lekötési objektumra.

A git visszaállításának belső működése

Szeretem ezt úgy gondolni, git resetmint egy parancsot, amely megfordítja a fent leírt folyamatot (változtatás bevezetése a munkakönyvbe , hozzáadás az indexhez , majd bekötés a lerakatba ).

Git visszaállítás három működési módja -  --soft, --mixedvagy --hard. Három szakaszként látom őket:

  • 1. szakasz - frissítés HEAD - git reset --soft
  • 2. szakasz - index frissítése  - git reset --mixed
  • 3. szakasz - frissítse a működő direktort  - git reset --hard

1. szakasz - frissítés HEAD( git reset --soft)

Először git resetfrissítse a HEADpontokat. Mert git reset --hard HEAD~1arra fog mozogni, amelyikre HEADmutat (a fenti példában master) HEAD~1. Ha a  — -softzászlót használják, git resetott megáll.

A fenti példánkat folytatva HEADrámutat commit 2, és így new_file.txtnem lesz része a jelenlegi elkötelezettség fájának. Ez azonban része lesz az indexnek és a munkarendnek .

Ha ránézünk git status, láthatjuk, hogy a fájl valóban szakaszos, de nem kötelező:

Más szavakkal, visszatértük a folyamatot abba a szakaszba, ahol használtuk git add, de még nem használtuk git commit.

2. szakasz - index frissítése a HEAD-hez ( git reset --mixed)

Ha használjuk git reset --mixed HEAD~1, akkor gitnem áll le, miután frissítettük HEADa (z master) ( ) értékre mutató pontokat HEAD~1. Az indexet a (már frissített) értékre is frissíti HEAD.

Példánkban ez azt jelenti, hogy az index állapota megegyezik a 2. kötelezettségvállalással :

Tehát a felhasználás előtt visszatértük a folyamatot a szakaszba git add - az újonnan létrehozott fájl immár része a működő dir-nek, de az index és a tár nem.

3. szakasz - frissítse a működő direktort az indexhez ( git reset --hard)

Segítségével git reset — hard HEAD~1frissítése után bármilyen HEADpontot ( master) a HEAD~1, valamint frissíti a mutató a (már frissítve) HEAD, gitmajd lépni, és frissíti a dolgozó dir , hogy néz ki, mint az index .

Példánkban ez azt jelenti, hogy a működő dir azonos állapotú lesz, mint az index, amelynek állapota már megegyezik a 2. kötelezettséggel :

Valójában a teljes folyamatot már a létrehozás előtt visszatértük my_file.txt.

Tudásunk felhasználása valós forgatókönyvekhez

Most, hogy megértettük a git resetműködését, alkalmazzuk ezt a tudást a nap megmentésére! ?

1. Hoppá! Tévedésből követtem el valamit.

Vizsgáljuk meg a következő forgatókönyvet. Létrehoztunk egy fájlt a karakterlánccal This is very importnt, megrendeztük és lekötöttük.

És akkor ... Hoppá! Rájöttünk, hogy gépelési hibánk van. ?

Nos, most már tudjuk, hogy ezt könnyedén meg tudjuk oldani. Visszaállíthatjuk az utolsó elkötelezettségünket, és a fájlt visszavezethetjük a működő könyvtárba git reset --mixed HEAD~1. Most szerkeszthetjük a fájlunk tartalmát, átállíthatjuk és újra elvégezhetjük.

Tipp: ebben a konkrét esetben használhatnánk git commit --amendaz itt leírtak szerint is.

2. Hoppá! Valamit rossz ágra köteleztem el - és szükségem van rá egy új ágon

Mindannyian ott voltunk. Végeztünk néhány munkát, majd elköteleztük magunkat ...

Ó, nem, elköteleztük magunkat a masterfióktelep mellett, bár létre kellett volna hoznunk egy új fióktelepet, majd ki kell adnunk a kérelmet. ?

Ebben a szakaszban hasznosnak tartom, hogy szemléltessük az állapotot, amelyben vagyunk, és hová szeretnénk eljutni:

Valójában három változás van az aktuális és a kívánt állapot között.

Először is, az newág rámutat a nemrég hozzáadott elkötelezettségünkre. Másodszor, masterrámutat az előző kötelezettségvállalásra. Harmadszor, HEADrámutat a new.

Három egyszerű lépéssel juthatunk el a kívánt állapotba:

Először tegyen newelágazási pontot a nemrég hozzáadott elkötelezettségre - ez egyszerűen felhasználható git branch new. Ezért elérjük a következő állapotot:

Másodszor mastermutasson rá az előző elköteleződésre (más szóval: a HEAD~1). Használatával megtehetjük git reset --hard HEAD~1. Ezért elértük a következő állapotot:

Végül szeretnénk ágon lenni new, vagyis HEADpontot tenni new. Ez előadással könnyen elérhető git checkout new.

Összességében:

  • git branch new
  • git reset --hard HEAD~1
  • git checkout new

3. Hoppá! Valamit rossz ághoz kötöttem - és szükségem van rá egy másik, már létező ágon

Ebben az esetben ugyanazokat a lépéseket tettük meg, mint az előző forgatókönyvben - elvégeztünk néhány munkát, majd elköteleztük magunkat ...

Ó, nem, elköteleztük magunkat a masterfióktelep mellett, bár el kellett volna köteleznünk magunkat egy másik, már létező ág mellett. ?

Térjünk vissza a rajztáblánkra:

Megint láthatjuk, hogy itt van néhány különbség.

Először a legutóbbi elkötelezettségre van szükségünk, hogy existingfióktelepben legyünk . Mivel masterjelenleg rámutat, egyszerűen megkérhetjük, githogy vegyük át a legutóbbi elkötelezettséget a masterfiókból, és alkalmazzuk az ilyen existingágra:

  • git checkout existing - váltás existingágra
  • git cherry-pick master - az masterág utolsó lekötésének alkalmazása az aktuális ( existing) ágra

Most elértük a következő állapotot:

Most csak mastera legutóbbi kötelezettségvállalásra kell rámutatnunk. Ehhez:

  • git checkout master - változtassa meg masterismét az aktív ágat .
  • git reset --hard HEAD~1 - most visszatértünk az eredeti ághoz.

És elértük a kívánt állapotot:

Összegzés

Ebben a bejegyzésben megtanultuk, hogyan git resetműködik, és pontosította a három üzemmódja van -  --soft, --mixedés --hard.

Ezután git resetnéhány valós kérdés megoldására alkalmaztuk tudásunkat git.

A működés módjának megértésével gitmagabiztosan kezelhetünk mindenféle forgatókönyvet, és értékelhetjük ennek az eszköznek a szépségét is?

A jövőbeni bejegyzésekben további gitparancsokra térünk ki, és arra, hogyan segíthetnek nekünk mindenféle nem kívánt helyzet megoldásában.

Omer Rosenbaum , a Swimm technológiai vezetője. Számítástechnikai képzési szakértő és a Checkpoint Security Academy alapítója. A számítógépes hálózatok szerzője (héberül) . Látogasson el a YouTube csatornámra .

További források

  • Rövid Git Internals sorozat a YouTube-on
  • Vizualizált bevezető a Git belsejéhez - tárgyak és ágak
  • Hardcore megszerzése - Repo készítése a Scratchból
  • Git Tools - Demystified visszaállítása (a Pro Git Bookból)