git restore
Команда git restore: как отменить изменения в рабочем дереве и снять файлы со стейджинга. Флаги --staged и --source с примерами.
Что делает git restore
Команда git restore копирует чистую версию файла в рабочее дерево, область индексирования или оба места сразу. Появившись в Git 2.23 вместе с git switch, она взяла на себя операции с отдельными файлами, которые раньше были частью перегруженной команды git checkout. Её задача — ответить на один вопрос: откуда взять правильную версию файла и куда её поместить?
Чтобы хорошо разобраться в команде, полезно знать «три дерева» Git: рабочее дерево (файлы, которые вы редактируете на диске), индекс (область индексирования — то, что записывает git add и что попадёт в следующий коммит), и HEAD (снимок вашего последнего коммита). git restore всегда перемещает содержимое из источника в получатель среди этих трёх деревьев. Два флага управляют этим:
--source=<rev>— откуда берётся чистая копия. По умолчанию из индекса, или изHEADпри использовании--staged.--stagedи/или--worktree— куда записывается копия. По умолчанию--worktree.
На этой странице рассматриваются повседневные сценарии: отброс правок, снятие со стейджинга, восстановление из старого коммита, восстановление удалённого файла, а также отличия restore от reset и revert.
Отмена изменений в рабочем дереве
По умолчанию git restore перезаписывает файл в рабочей директории версией из области индексирования (индекса). Если вы отредактировали файл и хотите отбросить эти правки:
git restore index.htmlФайл возвращается в последнее проиндексированное состояние (или в состояние HEAD, если он не был добавлен в индекс). Поскольку операция деструктивна — несохранённые правки теряются безвозвратно и не могут быть восстановлены через git reflog — Git намеренно даёт ей чёткое, явное имя, а не прячет за checkout.
Чтобы одновременно отбросить изменения во многих файлах, передайте директорию или pathspec. Это одна из немногих команд git restore, способных уничтожить большой объём работы одним нажатием клавиши, поэтому сначала проверьте незакоммиченные изменения с помощью git status:
git restore . # discard all changes in the current directory
git restore src/ # discard all changes under src/Снятие со стейджинга с помощью --staged
Чтобы убрать файл из области индексирования, не изменяя его содержимое на диске, используйте --staged. Это копирует версию из HEAD обратно в индекс, оставляя правки в рабочем дереве нетронутыми:
git restore --staged index.htmlЭто современная замена команды git reset HEAD <file>, и именно её Git предлагает в подсказке при выполнении git status после добавления файла в индекс:
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: index.htmlВосстановление из конкретного коммита
Опция --source позволяет взять содержимое файла из любого коммита, ветки или тега — не только из индекса или HEAD:
git restore --source=HEAD~2 config.ymlЭто возвращает отдельный файл к состоянию двухкоммитовой давности. Важно понимать, что при этом не происходит: команда не создаёт коммит и не перемещает указатель ветки. Старое содержимое попадает в рабочее дерево как обычное неиндексированное изменение, готовое к просмотру, добавлению в индекс и коммиту. В качестве источника можно использовать имя ветки (--source=main) или тег (--source=v1.0).
Восстановление удалённого файла
Если вы случайно удалили отслеживаемый файл и не зафиксировали удаление, git restore вернёт его из индекса или HEAD:
git restore app.jsПоскольку файл существует в известном правильном снимке, Git перезапишет его на диске точно в том виде, каким он был. (Если удаление уже зафиксировано в коммите, восстановите файл из более раннего коммита: git restore --source=HEAD~1 app.js.)
Сброс обеих копий одновременно
Сочетание --staged и --worktree полностью сбрасывает файл — как проиндексированную копию, так и копию на диске — к состоянию HEAD:
git restore --staged --worktree index.htmlЭто команда «сделать файл таким, как в последнем коммите, что бы я ни делал». Она отбрасывает как проиндексированные, так и не проиндексированные правки за один шаг.
Восстановление части файла
Как git add и git checkout, команда git restore поддерживает интерактивный режим. С флагом -p (или --patch) Git проходит по каждому блоку изменений и спрашивает, нужно ли его отбросить, позволяя отменить одни правки и сохранить другие:
git restore -p index.htmlЭто полезно, когда в одном файле есть несколько несвязанных изменений и нужно отменить только определённый эксперимент.
Основные параметры
| Команда | Описание |
|---|---|
git restore <file> | Отбрасывает изменения в рабочем дереве, восстанавливая файл из индекса. |
git restore --staged <file> | Снимает файл со стейджинга, восстанавливая копию в индексе из HEAD. |
git restore --staged --worktree <file> | Сбрасывает проиндексированную и рабочую копии к HEAD одновременно. |
git restore --source=<commit> <file> | Восстанавливает файл из конкретного коммита, ветки или тега. |
git restore -p <file> | Интерактивно отбрасывает только выбранные блоки изменений. |
git restore . | Отбрасывает все изменения в рабочем дереве текущей директории. |
restore vs reset vs revert
Эти три команды легко перепутать, поскольку все они что-то «отменяют», но работают на разных уровнях:
- git restore работает с файлами в рабочем дереве и индексе. Он никогда не перемещает указатели веток и не переписывает историю.
- git reset перемещает текущий указатель ветки и может изменять область индексирования — он работает на уровне коммитов.
- git revert создаёт новый коммит, отменяющий предыдущий, сохраняя существующую историю нетронутой.
Используйте restore, когда просто хотите, чтобы файл выглядел так, как в другом месте истории. Если нужно отбросить целые коммиты или переместить ветку — это задача для git reset. Если изменения уже запушены и доступны другим, используйте git revert, чтобы не переписывать историю, от которой зависят другие. Чтобы временно отложить изменения вместо их отбрасывания, смотрите git stash.
git restore <file> (форма по умолчанию) безвозвратно уничтожает незакоммиченные правки — они нигде не сохраняются и не могут быть восстановлены. Если они могут понадобиться, используйте вместо этого git stash.