На любой стадии может возникнуть необходимость что-либо отменить. Здесь мы рассмотрим несколько основных инструментов для отмены произведённых изменений. Будьте осторожны, ибо не всегда можно отменить сами отмены. Это одно из немногих мест в Git, где вы можете потерять свою работу если сделаете что-то неправильно.
Изменение последнего коммита
Одна из типичных отмен происходит тогда, когда вы делаете коммит слишком рано забыв добавить какие-то файлы, или напутали с комментарием к коммиту. Если вам хотелось бы сделать этот коммит ещё раз, вы можете выполнитьcommit
с опцией --amend
:
$ git commit --amend
Эта команда берёт индекс и использует его для коммита. Если после последнего коммита не было никаких изменений (например, вы запустили приведённую команду сразу после предыдущего коммита), то состояние проекта будет абсолютно таким же и всё, что вы измените это комментарий к коммиту.
Появится всё тот же редактор для комментариев к коммитам, но уже с введённым комментарем к последнему коммиту. Вы можете отредактировать это сообщение так же как обычно, и оно перепишет предыдущее.
Для примера, если после совершения коммита вы осознали, что забыли проиндексировать изменения в файле, которые хотели добавить в этот коммит, вы можете сделать что-то подобное:
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
Все три команды вместе дают один коммит — второй коммит заменяет результат первого.
Отмена индексации файла
В следующих двух разделах мы продемонстрируем как переделать изменения в индексе и в рабочей директории. Приятно то, что команда используемая для определения состояния этих двух вещей дополнительно напоминает о том как отменить изменения в них. Приведём пример. Допустим вы внесли изменения в два файла и хотите записать их как два отдельных коммита, но случайно набралиgit add *
и проиндексировали оба файла. Как теперь отменить индексацию одного из двух файлов? Комманда git status
напомнит вам об этом:
$ git add .
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# modified: README.txt
# modified: benchmarks.rb
#
Сразу после надписи “Changes to be committed
”, написано использовать git reset HEAD ... для исключения из индекса. Так что давайте последуем совету и отменим индексацию файла benchmarks.rb
:
$ git reset HEAD benchmarks.rb
benchmarks.rb: locally modified
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# modified: README.txt
#
# Changed but not updated:
# (use "git add ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory)
#
# modified: benchmarks.rb
#
Эта команда немного странновата, но она работает. Файл benchmarks.rb
изменён, но снова не в индексе.
Отмена изменений файла
Что если вы поняли, что не хотите оставлять изменения внесённые в файл benchmarks.rb
? Как быстро отменить изменения, вернуть то состояние, в котором он находился во время последнего коммита (или первоначального клонирования, или какого-то другого действия, после которого файл попал в рабочую директорию)? К счастью, git status
говорит как добиться и этого. В выводе для последнего примера, неиндексированная область выглядит следующим образом:
# Changed but not updated:
# (use "git add ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory)
#
# modified: benchmarks.rb
#
Здесь довольно ясно сказано как отменить сделанные изменения (по крайней мере новые версии Git’а, 1.6.1
и дальше, делают это; если у вас более старая версии, мы настоятельно рекомендуем обновиться, чтобы получить некоторые приятные удобные возможности). Давайте сделаем, то что написано:
$ git checkout -- benchmarks.rb
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# modified: README.txt
#
Как вы видите, изменения были отменены. Вы должны понимать, что это опасная команда: все сделанные вами изменения в этом файле пропали — вы просто скопировали поверх него другой файл. Никогда не используйте эту команду если вы не полностью уверены, что этот файл вам не нужен. Если вам нужно просто сделать, чтобы он не мешался, мы рассмотрим прятание (stash) и ветвление в следующей главе; эти способы обычно более предпочтительны.
Помните, что всё, что является частью коммита в Git, почти всегда может быть восстановлено. Даже коммиты, которые находятся на ветках, которые были удалены, и коммиты переписанные с помощью --amend
могут быть восстановлены (см. Главу 9 для восстановления данных). Несмотря на это, всё, что никогда не попадало в коммит, вы скорее всего уже не увидете снова.
Pro Git