Я хочу вернуться к более раннему коммиту. Как мне это сделать?
Вот что показывает команда 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-коммит оказался ошибочным, используйте этот ответ.
Комментариев нет:
Отправить комментарий