Страницы

Поиск по вопросам

воскресенье, 24 ноября 2019 г.

Как вернуться (откатиться) к более раннему коммиту?


Я хочу вернуться к более раннему коммиту. Как мне это сделать?

Вот что показывает команда git log:

$ git log
commit dddddd
Author: Me 
Date:   Thu Nov 4 18:59:41 2010 -0400

Add buzz

commit cccccc
Author: Me 
Date:   Thu Nov 4 05:13:39 2010 -0400

Add fizz

commit bbbbbb
Author: Me 
Date:   Thu Nov 4 00:55:06 2010 -0400

Add bar

commit aaaaaa
Author: Me 
Date:   Wed Nov 3 23:56:08 2010 -0400

Add foo

    


Ответы

Ответ 1



Этот вопрос можно понять по-разному: Что значит вернуться или откатиться: просто посмотреть, изменить содержимое рабоче области, изменить историю Git? Что именно откатить: рабочую область (worktree), индекс (область подготовки коммита staging area), текущую ветку, удаленную ветку? К какой позиции откатить: к индексу, к последнему коммиту, к произвольному коммиту? Обозначим начальную ситуацию на следующей схеме: (i) (wt) A - B - C - D - ? - ? ↑ master (HEAD) 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{0} (HEAD) 3.1.2 Индексированные и нет Эта команда отменяет все индексированные и неиндексированные изменения в рабоче области, сохраняя их в карман (stash). git stash save Конечное состояние: (wt) (i) A - B - C - D ? ↑ ↑ master stash{0} (HEAD) Восстановление несохраненных изменений: легко и просто. git stash apply Если stash совсем не нужен, его можно удалить. # удалить последнюю запись кармана git stash drop Подробнее про использование stash. После этого восстановить изменения всё ещё можно, но сложнее: How to recover a droppe 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-коммит оказался ошибочным, используйте этот ответ.

Комментариев нет:

Отправить комментарий