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, ни одно из которых не является необратимым. Любые изменения, которые вы делаете здесь, могут быть зафиксированы в ветке или сохранены для последующего использования.
Как в Git вернуться к последнему коммиту?
Решил посмотреть состояние проекта на пару коммитов назад. Дал команду:
git checkout хешСтарогоКоммита
Посмотрел, ничего не менял. Решил вернуться к последнему коммиту. Даю команду:
git checkout хешПоследнегоКоммита
Проект переключился на последний коммит. Но проект находится в ненормальном состоянии:
> git status HEAD detached at 9b93eec nothing to commit, working directory clean
Отчего так происходит? Как по-нормальному вернуться в последнее закоммиченное состояние проекта?
Но это по-моему слишком заковыристо для такого простого действия как «посмотреть что было и вернуться обратно».

Xintrea ★★★★★
13.08.15 13:12:42 MSK
git checkout master или git checkout HEAD
Deleted
( 13.08.15 13:18:45 MSK )

А что не так ? по ссылке все правильно.
joy4eg ★★★★★
( 13.08.15 13:19:27 MSK )

Возвращаться после однократного git checkout hash удобнее всего с помощью:
git checkout -
(Работает по аналогии с cd — .)
xaizek ★★★★★
( 13.08.15 13:24:56 MSK )
Последнее исправление: xaizek 13.08.15 13:28:55 MSK (всего исправлений: 1)
Ответ на: комментарий от Deleted 13.08.15 13:18:45 MSK

Часто вижу такую рекомендацию, но лично у меня эта команда правильно не работает. Git что ли из другой вселенной? Как был detached так и остается detached.
> git checkout HEAD > git status HEAD detached at 9b93eec nothing to commit, working directory clean
Сработала бессмысленная команда:
git checkout имяВеткиГдеВыНаходитесь
Вот она переносит проект в последнее состояние нормально.
Xintrea ★★★★★
( 13.08.15 13:26:19 MSK ) автор топика
Ответ на: комментарий от Deleted 13.08.15 13:18:45 MSK

Наверное, имелось в виду:
git checkout HEAD@
Так как восстановить сбитый HEAD переходом на него же не выйдёт.
xaizek ★★★★★
( 13.08.15 13:27:12 MSK )
Ответ на: комментарий от Xintrea 13.08.15 13:26:19 MSK
Часто вижу такую рекомендацию, но лично у меня эта команда правильно не работает.
HEAD names the commit on which you based the changes in the working tree
грубо говоря, этот shortcut контексто-зависим, и может означать много разных вещей.
это была правильная команда.
это не совсем точное название. в состоянии detached head, ты не находишься ни в какой ветке. git checkout branchname просто переключила ветку на ту что ты захотел.
waker ★★★★★
( 13.08.15 13:31:32 MSK )
Последнее исправление: waker 13.08.15 13:33:37 MSK (всего исправлений: 2)

git checkout ветка_с_которой_ты_работал
git reflog покажет тебе историю твоих перемещений по коммитам
Для того, чтобы «посмотреть состояние проекта на пару коммитов назад» не обязательно делать checkout, достаточно git show HEAD~2:путь_файла
annulen ★★★★★
( 13.08.15 13:33:23 MSK )

Вторую команду нужно заменить на git checkout имяИсходнойВетки .
Как вернуться (откатиться) к более раннему коммиту?
A , B , C , D — коммиты в ветке master .
(HEAD) — местоположение указателя HEAD.
(i) — состояние индекса Git. Если совпадает c (HEAD) — пуст. Если нет — содержит изменения, подготовленные к следующему коммиту.
(wt) — состояние рабочей области проекта (working tree). Если совпадает с (i) — нет неиндексированных изменений, если не совпадает — есть изменения.
↑ обозначает коммит, на который указывает определенная ветка или указатель.
Вот решения, в зависимости от задачи:
1. Временно переключиться на другой коммит
Если вам нужно просто переключиться на другой коммит, чтобы, например, посмотреть на его содержимое, достаточно команды git checkout :
git checkout aaaaaa (wt) (i) A - B - C - D ↑ ↑ (HEAD) master
Сейчас репозиторий находится в состоянии «detached HEAD». Чтобы переключиться обратно, используйте имя ветки (например, master ):
git checkout master
2. Переключиться на коммит и продолжить работу с него
Если вы хотите продолжить работу с другого коммита, вам понадобится новая ветка. Можно переключиться и создать ее одной командой:
git checkout -b имя-новой-ветки aaaaaa (wt) (i) A - B - C - D ↑ ↑ new master (HEAD)
3. Удалить изменения в рабочей области и вернуть ее к состоянию как при последнем коммите.
(i) (wt) A - B - C - D - ? - ? ↑ master (HEAD)
3.1 Безопасно — с помощью кармана (stash)
3.1.1 Только неиндексированные
Можно удалить прикарманить только те изменения, которые еще не были индексированы (командой add ):
git stash save --keep-index
(wt) (i) A - B - C - D - ? ? ↑ ↑ master stash (HEAD)
3.1.2 Индексированные и нет
Эта команда отменяет все индексированные и неиндексированные изменения в рабочей области, сохраняя их в карман (stash).
git stash save
(wt) (i) A - B - C - D ? ↑ ↑ master stash (HEAD)
Восстановление несохраненных изменений: легко и просто.
git stash apply
Если stash совсем не нужен, его можно удалить.
# удалить последнюю запись кармана git stash drop
После этого восстановить изменения всё ещё можно, но сложнее: How to recover a dropped stash in Git?
3.2 Опасный способ
Осторожно! Эта команда безвозвратно удаляет несохраненные текущие изменения из рабочей области и из индекса Если они вам все-таки нужны, воспользуйтесь git stash .
Восстановление несохраненных изменений: неиндексированные потеряны полностью, но вы можете восстановить то, что было проиндексировано.
Здесь мы будем использовать git reset —hard
git reset --hard HEAD
(wt) (i) A - B - C - D - х - х ↑ master (HEAD)
4. Перейти к более раннему коммиту в текущей ветке и удалить из нее все последующие (неопубликованные)
Осторожно! Эта команда переписывает историю Git-репозитория. Если вы уже опубликовали ( git push ) свои изменения, то этот способ использовать нельзя (см. почему). Используйте вариант из пункта 5 ( git revert ).
4.1 При этом сохранить изменения в индекс репозитория:
git reset --soft bbbbbb
После этого индекс репозитория будет содержать все изменения от cccccc до dddddd . Теперь вы можете сделать новый коммит (или несколько) на основе этих изменений.
(wt) (i) A - B - C - D ↑ master (HEAD)
4.2 Сохранить изменения в рабочей области, но не в индексе.
git reset bbbbbb
Эта команда просто перемещает указатель ветки, но не отражает изменения в индексе (он будет пустым).
(i) (wt) A - B - C - D ↑ master (HEAD)
4.3 Просто выбросить изменения.
Осторожно! Эта команда безвозвратно удаляет несохраненные текущие изменения. Если удаляемые коммиты не принадлежат никакой другой ветке, то они тоже будут потеряны.
Восстановление коммитов: Используйте git reflog и этот вопрос чтобы найти и восстановить коммиты; иначе сборщик мусора удалит их безвозвратно через некоторое время.
Восстановление несохраненных изменений: неиндексированные потеряны полностью, но вы можете восстановить то, что было проиндексировано.
(i) (wt) A - B - C - D - ? - ? ↑ master (HEAD)
git reset --hard bbbbbb
(wt) (i) A - B - C - D - х - х ↑ master (HEAD)
5. Отменить уже опубликованные коммиты с помощью новых коммитов
Воспользуйтесь командой git revert . Она создает новые коммиты, по одному на каждый отменяемый коммит. Таким образом, если нужно отменить все коммиты после aaaaaa :
# можно перечислить отменяемые коммиты git revert bbbbbb cccccc dddddd # можно задать диапазон от более раннего к более позднему (новому) git revert bbbbbb..dddddd # либо в относительных ссылках git revert HEAD~2..HEAD # можно отменить коммит слияния, указывая явным образом номер предка (в нашем примере таких нет): git revert -m 1 abcdef # после этого подтвердите изменения: git commit -m'детальное описание, что и почему сделано'
Восстановление: Если revert-коммит оказался ошибочным, используйте этот ответ.
Что такое коммит git? Как вернуться (откатиться) к более раннему коммиту?
Когда разработка идет «по — мелкому», тогда, возможно, разработчики и не сталкиваются с Git-системами, потому что в их использовании просто нет смысла. Например, если заниматься разработкой одностраничных сайтов, то Git не нужен. Но когда разработка ведется над серьезными проектами, тогда Git обязательно присутствует.
Git — это виртуальная систем а управления версией исходного кода программы. С помощью Git можно создавать «контрольные точки» в разработке. Например, над программой работают несколько разработчиков какое-то время. Появились первые результаты, которые удовлетворяют требования к программе, тогда их фиксируют. Далее над программой продолжается работа. Если что-то пошло не так, тогда всегда есть возможность вернуться в «контрольную точку» и продолжать работать над программой. Если изменения всех устраивают, тогда фиксируют следующую «контрольную точку» и т. д. Таким образом появляется ветвь развития программы с «контрольными точками», к которым всегда можно вернуться.
Благодаря Git, над программами можно экспериментировать. Например, с определенной «контрольной точки» можно развивать несколько ветвей программы с различным экспериментальным функционалом, а потом выбрать что лучше.
Что такое коммит в Git?
Каждая «контрольная точка», о которых мы писали чуть выше , на профессиональном сленге называется коммит. По сути, коммит Git — это некий пакет с кодом, который хранит предыдущую версию программы с добавленными изменениями.
Когда над программой ведется активная работа, коммиты создаются довольно часто. Среди разработчиков ходит негласное правило, что в один коммит добавляют до 10 важных изменений программы, но в каждой команде цифра изменений может быть разная. Из-за небольшого количества вносимых изменений коммитов получается много. Однако такое положение нужно для того, чтобы всегда была возможность откатить изменения до последнего работающего коммита с минимальными потерями в коде. К примеру, если вносить по 100 изменений в один коммит и на каком-то этапе обнаружить о ш ибку в программе, тогда нужно будет откатить Git-комит и потерять сразу 100 изменений, а если в коммите содержатся только по 10 изменений, тогда будет потеряно только 10.
Откатить коммит в Git — это довольно частая задача, потому что главное правило программирования звучит просто: ошибки допускают все независимо от квалификации программиста. В принципе, Git-система как раз была придумана для того, чтобы программисты в случае чего не возвращались в самое начало рабочего процесса, а всего лишь к ближайшему рабочему коммиту.
Благодаря ко м митам в Git, разработчики отлично могут работать в команде, которая имеет разные взгляды на разработку. Допустим есть некая программа, которая зафиксирована в определенном коммите. Перед командой стоит задача организовать какой-то дополнительный функционал. Реализовать функционал можно по-разному, на этом фоне возникают споры. В этом случае команда легко может разделиться и создать несколько рабочих веток программы от общего коммита, чтобы проверить гипотезу разработки нужного функционала.
В общем, коммит и Git — это неразделимые вещи и о них можно много говорить. Сегодня хотелось бы подробнее остановиться на одной важной вещи — показать, как в Git откатить изменения до последнего работающего коммита.
Git: откатить изменения до работающего коммита
На самом деле, откатить коммит в Git — это не совсем простая задача. Вернее она может быть простой в определенных ситуациях, например, когда вы работаете над программой самостоятельно и от вашего коммита зависит только ваша работа. Таким образом вы легко можете удалять, добавлять, откатывать коммиты — всё это происходит исключительно под вашим контролем. Сложнее в Git откатить изменения до какого-то коммита, когда над программой работают несколько разработчиков в нескольких ветках и каждый ваш коммит может быть использован другими разработчиками. В общем, ситуации могут быть разными, поэтому будьте осторожны и внимательны. А мы покажем как можно откатиться к коммиту несколькими способами, а вы уже выберите тот, который подходит именно вам.
Удаляем неопубликованные коммиты
Этот способ вам подойдет, если вы пока еще не опубликовали коммиты в репозитории, например в GitHub. Для этого действия используется простая команда:
$ git reset — -hard
Работать с этой командой нужно осторожно, потому что она безвозвратно удаляет неопубликованные коммиты и можно потерять что-то стоящее, из того что было в коде. Если вы не до конца уверены, что хотите полностью удалить неопубликованный коммит или просто хотите пока сохранить новые изменения, чтобы потом их доработать, если что, тогда воспользуйтесь более щадящей командой:
$ git stash
Эт а команда откатит вас до последнего коммита, но сохранит все созданные вами изменения, не добавляя их в основную ветку.
Удаляем опубликованные коммиты
Может быть такая ситуация, что вы внесли изменения в код и отправили их в GitHub. В этом случае, если использовать команду «reset», тогда можно нарваться на большие неприятности, потому что с помощью этой команды переписывается история. Не будем вдаваться в подробности, но скажем, что вам это не нужно
В данном случае лучше воспользоваться командой:
$ git revert
С помощью этой команды происходит простая отмена внесенных изменений в конкретном коммите, над которым вы до сих пор работали. Фактически создается новый коммит без удаления предыдущих, тем самым сохраняется история удаленного репозитория и не наносится большой вред.
Временно откатить коммит в Git
Для этого используется команда:
$ git checkout
Фактически она отменяет фиксацию последнего коммита и позволяет вам временно вернуться к предыдущему в вашем репозитории. В само дерево разработки никаких изменений не вносится. Перед вами открывается содержимое предыдущего коммита и вы даже можете вносить в него изменения и потом зафиксировать для дальнейшего использования.
Заключение
Сегодня мы вас познакомили с коммитами в Git. Теперь вы знаете, что коммит в Git — это «контрольная точка», к которой вы можете всегда вернуться и продолжить работу над программой именно с нее.
В процессе работы с Git и коммитами очень важный навык — это умение откатить изменения до коммита в Git, который вас устраивал. Мы показали несколько способов как можно откатить коммит в Git. В зависимости от вашей ситуации можете воспользоваться любым из них.
Мы будем очень благодарны
если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.