Как вернуться к старому коммиту
Перейти к содержимому

Как вернуться к старому коммиту

  • автор:

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. В зависимости от вашей ситуации можете воспользоваться любым из них.

Мы будем очень благодарны

если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *