Случай, который происходит довольно редко, но метко - это "Ааааа, я накосячил в git!!!". У меня случилось такое сегодня, когда я сделал rebase со squash'ем локальной ветки, не имея этих коммитов в другой ветке. Git не задумываясь слил мои коммиты в один и перенёс его, а мне нужно было сохранить исходную ветку, создав новый squash-коммит.
В общем, здесь я вспомнил про логи и отмену изменений. Git умеет отменять практически любые изменения. Все связанное с передвижением HEAD'а можно отменить reset'ом. В моём случае отмена rebase делается следующим способом...
Смотрим последние изменения (безопасно):
git reflog # для выхода жмем q
# или смотреть последние 10 действий
git reflog -n 10
# или тоже самое, но короче
git reflog -10
Например, мой вывод
$ git reflog -n 6
703952e HEAD@{0}: rebase -i (finish): returning to refs/heads/BPN-3546
703952e HEAD@{1}: rebase -i (squash): BPN-3546 Add content type for Gauge in Drupal
9a23f7e HEAD@{2}: rebase -i (squash): # This is a combination of 2 commits.
c1b984f HEAD@{3}: rebase -i (pick): BPN-3546 Add content type for Gauge in Drupal
c6be61c HEAD@{4}: rebase -i (start): checkout refs/heads/Gauge
cf81cc3 HEAD@{5}: commit (amend): BPN-3546 Add content type for Gauge in Drupal
Дальше находим необходимую точку и откатываем код до её состояния. Здесь я вижу, что последние 5 чекпоинтов связаны с ребейзом. Я их пропускаю и двигаю HEAD назад на 6 изменений.
--hard
будет означать, что добавленные изменения будут удалены.Например, если вы откатываете коммит, в котором добавили файл, то после отката этот файл будет удалён из репозитория.Здесь можно использовать флаг
--soft
, который означает, что после отката коммита файл останется как не зафиксированные изменения.
git reset --hard HEAD@{5}
# для Windows могут понадобиться кавычки
git reset --hard "HEAD@{5}"