Skip to content

Отмена изменений в GIT

Иногда случается «Аааа, я накосячил в Git!!!». Например, сделали интерактивный rebase с squash'ем, слили несколько коммитов в один, а потом поняли, что исходная история нужна.

К счастью, Git умеет отменять почти всё, что связано с движением HEAD.

Смотрим историю действий через reflog

git reflog показывает историю перемещений HEAD:

bash
git reflog          # полный список (q для выхода)
git reflog -n 10    # последние 10 действий
git reflog -10      # короткая запись того же

Пример вывода:

text
$ 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

Нас интересует момент до неудачного rebase.

Важно: нельзя «отменить одно старое действие в середине». Можно только переместить HEAD в нужную точку, отбросив все изменения после неё.

Возврат в прошлую точку

Например, нужно вернуть состояние на HEAD@{5}:

bash
git reset --hard HEAD@{5}

На Windows может понадобиться обернуть ссылку в кавычки:

bash
git reset --hard "HEAD@{5}"

Пара слов о --hard и --soft

  • --hard:
    • обновляет и HEAD, и содержимое рабочего каталога;
    • добавленные коммитами файлы будут удалены из дерева.
  • --soft:
    • двигает HEAD, но оставляет файлы как нестаженные изменения.

Документация для погружения:

  • git rebase — перемещение коммитов;
  • git reset — отмена изменений;
  • «Git Tools — Rewriting History» в книге Pro Git.