Git: вернуться к предыдущему коммиту
Если я чему-то научился за 15 с лишним лет программирования, так это то, что ошибки встречаются часто, и я их много делаю. Это в равной степени относится и к инструментам контроля версий. Независимо от того, случайно ли вы зафиксировали изменения или просто поняли, что ваш предыдущий зафиксированный код - это не то, что вам нужно, часто вам потребуется отменить предыдущий коммит в Git.
В этой статье я покажу несколько способов отменить ваши коммиты, в зависимости от вашего варианта использования. Это сложная тема (которая относится ко многим темам Git в целом), поэтому убедитесь, что вы следуете инструкциям, которые лучше всего соответствуют вашим потребностям.
Удалить неопубликованные коммиты
Если вы еще не опубликовали свои коммиты в удаленном репозитории, таком как GitHub, вы можете по существу удалить предыдущие коммиты с помощью команды reset.
Хотя это эффективное решение, оно опасное, поскольку вы переписываете историю и оставляете «удаленные» коммиты без ссылок или «осиротевшими». Единственный способ найти и восстановить эти несвязанные коммиты - это git reflog.
Команда reset имеет три различных параметра, два из которых мы опишем здесь:
$ git reset --hard
Используя опцию --hard, все возвращается обратно к указанному коммиту. Это включает в себя ссылки на историю коммитов, промежуточный индекс и ваш рабочий каталог.
Это означает, что с помощью этой команды вы не только вернетесь к предыдущей фиксации, но и потеряете все рабочие изменения в процессе. Чтобы не потерять какие-либо рабочие изменения, вы можете использовать команды stash и stash pop:
$ git stash $ git reset --hard$ git stash pop
Команда stash сохраняет ваши рабочие изменения (без каких-либо комитов или изменений в дереве), а затем stash pop возвращает их обратно.
Другим вариантом, который вы можете рассмотреть, является параметр --soft. Эта опция работает так же, как git reset --hard
$ git reset --soft
Удаление опубликованных коммитов
Допустим, вы зафиксировали свой код, а затем отправили его в удаленный репозиторий. На этом этапе настоятельно рекомендуется не использовать что-то вроде git reset, поскольку вы переписываете историю.
Вместо этого рекомендуется использовать команду revert. Эта команда работает, отменяя изменения, которые были внесены в указанный коммит, создавая новый коммит и фактически не удаляя предыдущие коммиты. Это идеально для опубликованных изменений, потому что тогда реальная история репозитория сохраняется. Вот пример:
$ git revert
Допустим, в вашем репозитории есть текстовый файл со следующим содержанием
This is my sample text
И вы изменяете его на:
This is my awesome sample text
Ваша история коммитов может выглядеть примерно так:
$ git log --pretty=oneline 676ec97a9cb2cebbb5c77904bbc61ced05b86f52 Added 'awesome' to text 735c5b43bf4b5b7107a9cc3f6614a3890e2889f6 Initial commit
Если мы решили, что нам больше ненужно слово «awesome» в нашем тексте, но мы не хотим удалять коммит 676ec, мы можем использовать revert, чтобы отменить это изменение:
$ git revert 676ec [master f68e546] Revert "Added 'awesome' to text" 1 file changed, 1 insertion(+), 1 deletion(-)
Получив приглашение ввести сообщение о коммите, мы теперь можем видеть в нашей истории коммитов, что фактически существует новый коммит:
$ git log --pretty=oneline f68e546ac2ae240f22b2676b5aec499aab27f1ca Revert "Added 'awesome' to text" 676ec97a9cb2cebbb5c77904bbc61ced05b86f52 Added 'awesome' to text 735c5b43bf4b5b7107a9cc3f6614a3890e2889f6 Initial commit
В результате этого первый и третий коммиты представляют одно и то же состояние проекта. Коммит был отменен, и история не была потеряна.
Обратите внимание, что есть несколько других способов использовать эту команду, например, если вы хотите вернуть обратно 2 коммита, вы можете использовать:
git revert HEAD~2
Или, если вы хотите отменить много непостоянных коммитов, вы указываете их индивидуально:
git revert 676ec 735c5
Временно оформить предыдущий коммит
«Отмена фиксации» означает, что вы временно хотите вернуться к предыдущему состоянию в своем репозитории, но без внесения каких-либо реальных изменений в дерево. В этом случае вы, вероятно, просто захотите проверить фиксацию, что позволит вам вернуться к мастеру или любому другому состоянию, когда вы закончите:
$ git checkout
Это изменит ваш рабочий каталог на содержимое этого коммита, а также на местоположение, на которое указывает HEAD, ни одно из которых не является необратимым. Любые изменения, которые вы делаете здесь, могут быть зафиксированы в ветке или сохранены для последующего использования.