Git
Chapters ▾ 2nd Edition

2.4 Основе програма Гит - Опозив

Опозив

У било ком тренутку можете пожелети да нешто опозовете (undo). Овде ћемо обрадити неколико основних алата за опозив радњи. Будите опрезни, јер не можете увек да опозовете неке од ових опозива. Ово је једна од ретких области програма Гит где можете изгубити неки део вашег рада у случају ако поступите на погрешан начин.

Чест случај када је потребан опозив се јавља онда када комитујете прерано и можда заборавите да додате неке фајлове, или погрешно напишете своју комит поруку. Ако желите да поново урадите тај комит, направите додатне измене које сте заборавили, стејџујте их и поново комитујте опцијом --amend:

$ git commit --amend

Ова команда узима ваш стејџ и користи га за комит. Ако од последњег комита нисте направили никакве измене (на пример, покренете ову команду одмах након последњег комита), онда ће снимак изгледати потпуно исто и све што ћете променити је комит порука.

Појављује се исти едитор за комит поруку, али се у њему већ налази укуцана порука из претходног комита. Поруку можете уредити као и увек, али тиме преписујете претходни комит.

Као пример, ако комитујете и онда схватите да сте заборавили да стејџујете промене у фајлу који сте желели да додате у овај комит, можете да урадите нешто овако:

$ git commit -m 'Initial commit'
$ git add заборављени_фајл
$ git commit --amend

На крају остаје само један комит — други комит замењује резултате првог.

Белешка

Важно је да разумете да када преправљате свој последњи комит, ви га уствари не поправљате већ га комплетно замењујете потпуно новим, побољшаним комитом који склања стари с пута и на његово места поставља нови комит. У суштини, исто је као да се претходни комит није ни догодио, па се неће ни приказивати у историји вашег репозиторијума.

Очигледна вредност преправљања комитова је у томе што мала побољшања свог последњег комита можете да урадите без затрпавања историје вашег репозиторијума порукама као што су „Уупс, заборавио сам да додам фајл” или „Аххх, исправка грешке у куцању у последњем комиту”.

Белешка

Преправљајте само комите који су још увек у локалу и нису гурнути негде. Преправљање комита који су раније гурнути и форсирано гурање гране ће правити проблеме вашим сарадницима. За више детаља о томе шта се дешава ако ово урадите, као и начин за опоравак ако се налазите на пријемном крају, прочитајте Опасности ребазирања.

Уклањање фајла са стејџа

Следећа два одељка показују како да радите са променама на стејџу и радном директоријуму. Добро је то што вас команда коју користите да би одредили стање ове две области такође подсећа и на начин за опозив промена које над њима направите. На пример, рецимо да сте променили два фајла и да желите да их комитујете као две посебне измене, али сте случајно укуцали git add * и тако их оба додали на стејџ. Како да један од њих склоните са стејџа? Команда git status вас подсећа на то:

$ git add *
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README
    modified:   CONTRIBUTING.md

Одмах испод текста „Changes to be committed” пише да треба да употребите git reset HEAD <file>…​ ако фајл желите да уклоните са стејџа. Тај савет ћемо искористити да фајл CONTRIBUTING.md уклонимо са стејџа:

$ git reset HEAD CONTRIBUTING.md
Unstaged changes after reset:
M	CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

Ова команда је помало чудна, али обавља посао. Фајл CONTRIBUTING.md је измењен али поново није на стејџу.

Белешка

Тачно је да git reset може бити опасна команда, посебно ако је позовете са заставицом --hard. Међутим, у случају који је описан изнад, фајл у радном директоријуму се не дира, тако да је команда релативно сигурна.

Засад је овај чаробни позив све што је потребно да знате о git reset команди. Много детаљније ћемо испитати шта тачно ради reset у Демистификовани ресет када ћемо показати и како да овладате њоме и постигнете неке веома занимљиве ствари.

Уклањање измена са измењеног фајла

Шта ако одлучите да не желите да задржите измене у фајлу CONTRIBUTING.md? Како да једноставно уклоните измене — да га вратите на стање у каквом је био када сте последњи пут начинили комит (или урадили почетно клонирање, или како год га поставили у радни директоријум)? Срећом, git status вам говори како и то да урадите. У прошлом примеру излаза, фајлови који нису били на стејџу били су представљени овако:

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

Каже вам како да експлицитно одбаците промене које сте направили. Хајде да урадимо то што нам саветује:

$ git checkout -- CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README

Можете видети да су се промене вратиле на старо.

Важно

Важно је да разумете да је git checkout -- <фајл> опасна команда. Све локалне промене које сте направили над тим фајлом су нестале — програм Гит га је управо преписао последњом стејџованом или комитованом верзијом. Никада немојте да користите ову команду осим ако нисте потпуно сигурни да вам промене које сте направили више не требају.

Ако ипак желите да задржите промене које сте направили у фајлу, али за сада не желите да вам стоји на путу, у Гранање у програму Гит ћете сазнати како да употребите скривање (stashing) и гранање (branching); обично су то бољи начини за рад.

Упамтите, у програму Гит се све што је комитовано скоро увек може опоравити. Чак и комитови који су били на гранама које су обрисане, или комитови који су преписани --amend комитом могу да се опораве (погледајте Опоравак података у вези опоравка података). Ипак, све што изгубите, а никад није било комитовано, вероватно више никад нећете видети.

Опозив ствари са git restore

Верзија 2.23.0 програма Гит је увела нову команду: git restore. У суштини је то алтернатива команди git reset коју смо управо описали. Од верзије 2.23.0 програма Гит надаље, програм Гит ће за многе операције опозива уместо git reset користити git restore.

Хајде да поново прођемо кроз наше кораке, опозовемо ствари командом git restore уместо са git reset.

Уклањање фајла са стејџа помоћу git restore

Следећа два одељка показују како да радите са изменама стејџа и радног директоријума директно помоћу команде git restore. Згодно је што вас команда коју користите да одредите статус те две области уједно и подсећа како да опозовете промене које начините над њима. На пример, претпоставимо да сте изменили два фајла и желите то да комитујете као две одвојене измене, али сте случајно откуцали git add * и стејџовали оба. Како да један од њих склоните са стејџа? Команда git status вас подсећа:

$ git add *
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   CONTRIBUTING.md
	renamed:    README.md -> README

Непосредно испод текста „Changes to be committed” пише „use git restore --staged <file>…​ to unstage” (употребите git restore --staged <фајл>…​ да уклоните са стејџа). Дакле, хајде да искористимо овај савет и уклонимо са стејџа фајл CONTRIBUTING.md:

$ git restore --staged CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	renamed:    README.md -> README

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   CONTRIBUTING.md

Фајл CONTRIBUTING.md је измењен, али је поново ван стејџа.

Уклањање промена из измењеног фајла помоћу git restore

Шта ако схватите да не желите задржати измене над фајлом CONTRIBUTING.md? Како једноставно можете да уклоните измене — тј. да га вратите у стање у коме је био када сте направили последњи комит (или урадили почетно клонирање, или шта год урадили да га поставите у радни директоријум)? Срећом, git status вам такође говори како и то да урадите. У излазу последњег примера, област ван стејџа изгледа овако:

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   CONTRIBUTING.md

Ово вам говори прилично директно како да одбаците измене које сте направили. Хајде да урадимо то што каже:

$ git restore CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	renamed:    README.md -> README
Важно

Важно је да разумете да је git restore <фајл> опасна команда. Све локалне промене које сте направили над тим фајлом су нестале — програм Гит га је управо преписао последњом стејџованом или комитованом верзијом. Никада немојте да користите ову команду осим ако нисте потпуно сигурни да вам промене које сте направили више не требају.