Git
Chapters ▾ 2nd Edition

2.4 Основи на Git - Възстановяване на направени действия

Възстановяване на направени действия

Във всеки един момент може да се окаже, че искате да отмените дадена промяна по проекта. Тук ще разгледаме някои основни средства за отмяна на промени. Бъдете внимателни, защото не винаги може да отмените отмяна! Това е една от малките области в Git, където можете да загубите част от данните си, ако не действате прецизно.

Едно от най-честите действия по отмяна е да направите къмит твърде рано и да сте забравили да добавите няколко файла или да сте объркали commit съобщението. Ако искате да опитате този къмит отново, направете забравените промени, индексирайте ги и можете да къмитнете отново с параметъра --amend:

$ git commit --amend

Тази команда взема съдържанието на индекса и го използва за къмита. Ако не сте правили промени от последния къмит (например, пускате командата веднага след предишния къмит), тогава вашият snapshot ще изглежда по идентичен начин и единственото нещо, което ще промените е commit съобщението.

Ще се отвори същия редактор, но със заредено съобщението от последния къмит. Можете да промените съобщението както обикновено, но то ще се презапише върху предишния ви къмит.

Като пример, ако къмитнете и веднага след това се сетите, че не сте индексирали промените във файл, който искате да влиза в къмита, можете да направите следното:

$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend

Ще си останете с един къмит — вторият замества резултатите от първия.

Note

Важно е да се запомни, че когато коригирате последния къмит, го заменяте с изцяло нов, подобрен такъв, който изцяло замества стария. По същество историята ще изглежда така, сякаш предишния къмит никога не се е случвал и няма да се показва в нея.

Очевидната полза от amending къмитите е, че можете да правите малки промени по последния къмит, без да трябва да задръствате историята със съобщения от сорта на “упс, забравих да добавя файл” или “поправям грешка в последния къмит”.

Изваждане на файл от индекса

Следващите две секции демонстрират как се работи с индексната област и промените в работната директория. Хубавото е, че командата, която използвате за да определите статуса на тези две области, също така ви подсказва и как да отменяте направени в тях промени. За пример, нека кажем, че сте променили два файла и искате да ги къмитнете като две отделни промени, но неволно сте изпълнили 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>... to unstage. Да ползваме този съвет за да де-индексираме файла 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 сега си е променен, но вече не е в индекса

Note

Вярно е, че git reset може да се окаже опасна команда, особено ако ѝ подадете флага --hard. Обаче, в горния случай, файлът в работната ви директория е недокоснат, така че тя е сравнително безопасна.

Към момента, това мистериозно извикване е всичко, което трябва да знаете за git reset командата. Ще навлезем в много по-дълбоки подробности за това какво прави 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

Можете да се уверите, че промените изчезнаха.

Important

Важно е да се помни, че git checkout -- <file> е опасна команда. Всички локални промени, които сте правили по този файл са изчезнали необратимо — Git просто заменя файла с най-скоро къмитнатата му версия. Никога не ползвайте тази команда, освен ако не сте абсолютно сигурни, че не желаете промените във файла.

Ако желаете да запазите промените си по файла, но все още държите да пазите този файл настрани от проекта към дадения момент, има по-добри начини да го направите, ще ги разгледаме в материала за скриване (stashing) и клонове код (branchingКлонове в Git).

Помнете, всичко което е къмитнато в Git може почти винаги да бъде възстановено по-късно. Дори къмити, които са били в изтрити клонове или комити презаписани с къмит от тип --amend, могат да бъдат възстановени (вижте Възстановяване на данни за повече информация). Обаче, всичко което загубите и не е било къмитното - най-вероятно няма да може да се възстанови.