git-reset
Название
git-reset — устанавливает HEAD или индекс в известное состояние
Краткое описание
git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>] git reset [-q] [<tree-ish>] [--] <pathspec>… git reset [-q] [--pathspec-from-file=<file> [--pathspec-file-nul]] [<tree-ish>] git reset (--patch | -p) [<tree-ish>] [--] [<pathspec>…]
Описание
git reset выполняет одно из следующих действий:
-
gitreset[<mode>] <commit> изменяет коммит, на который указываетHEAD. Это позволяет отменять различные операции Git, например commit, merge, rebase и pull. -
Если указать файлы или каталоги либо передать
--patch,gitresetобновляет подготовленную версию указанных файлов.-
gitreset[<mode>] [<commit>] -
Устанавливает указатель вершины текущей ветки (
HEAD) на<commit>. В зависимости от<mode>также обновляет рабочий каталог и/или индекс в соответствии с содержимым<commit>. По умолчанию<commit>имеет значениеHEAD. Перед выполнением операцииORIG_HEADустанавливается в вершину текущей ветки.Значением
<mode>должен быть один из следующих параметров (по умолчанию--mixed):-
--mixed -
Оставляет рабочий каталог без изменений. Обновляет индекс в соответствии с новым
HEAD, поэтому ничего не будет подготовлено к коммиту.Если указан
-N, удалённые пути помечаются как предназначенные для добавления (см. git-add[1]). -
--soft -
Оставляет файлы рабочего дерева и индекс без изменений. Например, если у вас нет подготовленных изменений, можно использовать git reset --soft HEAD~5; git commit, чтобы объединить последние 5 коммитов в один. Это работает даже при наличии изменений в рабочем дереве: они останутся нетронутыми, однако такое использование может привести к путанице.
-
--hard -
Перезаписывает все файлы и каталоги версиями из
<commit>и может перезаписать неотслеживаемые файлы. Отслеживаемые файлы, отсутствующие в<commit>, удаляются, чтобы рабочее дерево соответствовало<commit>. Обновляет индекс в соответствии с новымHEAD, поэтому ничего не будет подготовлено к коммиту. -
--merge -
Сбрасывает индекс и обновляет файлы в рабочем дереве, отличающиеся между
<commit>иHEAD, но сохраняет те, которые отличаются между индексом и рабочим деревом (то есть имеют изменения, не добавленные в индекс). Предназначен главным образом для сброса неслитых записей индекса, например оставшихся послеgitam-3илиgitswitch-mв определённых ситуациях. Если файл, отличающийся между<commit>и индексом, содержит непроиндексированные изменения, сброс прерывается. -
--keep -
Сбрасывает записи индекса и обновляет файлы в рабочем дереве, отличающиеся между
<commit>иHEAD. Если файл, отличающийся между<commit>иHEAD, содержит локальные изменения, сброс прерывается. -
--recurse-submodules -
--no-recurse-submodules -
При обновлении рабочего дерева использование
--recurse-submodulesтакже рекурсивно сбрасывает рабочие деревья всех активных подмодулей в соответствии с коммитом, записанным в суперпроекте, и переводитHEADподмодулей в отсоединённое состояние на этом коммите.
-
-
gitreset[-q] [<tree-ish>] [--] <pathspec>... -
gitreset[-q] [--pathspec-from-file=<file> [--pathspec-file-nul]] [<tree-ish>] -
Для всех указанных файлов или каталогов устанавливает подготовленную версию в версию из заданного коммита или дерева (по умолчанию используется
HEAD).Это означает, что
gitreset<pathspec> — противоположностьgitadd<pathspec>: она отменяет подготовку всех изменений указанных файлов или каталогов. Это эквивалентно командеgitrestore--staged<pathspec>....В этом режиме
gitresetобновляет только индекс (не обновляяHEADили файлы рабочего дерева). Чтобы обновить как файлы, так и записи индекса, используйте git-restore[1]. -
gitreset(--patch|-p) [<tree-ish>] [--] [<pathspec>...] -
В интерактивном режиме выбирает изменения из различий между индексом и указанным коммитом или деревом (по умолчанию используется
HEAD). Выбранные изменения применяются к индексу.Это означает, что
gitreset-p— противоположностьgitadd-p, то есть её можно использовать для выборочной отмены подготовки изменений. О том, как использовать параметр--patch, см. раздел «Интерактивный режим» в git-add[1].
-
Различия между этими тремя командами описаны в разделе «Reset, restore and revert» руководства git[1].
Параметры
-
-q -
--quiet -
Не выводить сообщения, сообщать только об ошибках.
-
--refresh -
--no-refresh -
Обновляет индекс после смешанного сброса. Включено по умолчанию.
-
--pathspec-from-file=<file> -
Спецификация путей передаётся в
<file>, а не в аргументах командной строки. Если<file>в точности равен-, используется стандартный ввод. Элементы спецификации путей разделяются символамиLFилиCR/LF. Элементы спецификации путей можно заключать в кавычки, как описано для переменной конфигурацииcore.quotePath(см. git-config[1]). См. также--pathspec-file-nulи глобальную переменную--literal-pathspecs. -
--pathspec-file-nul -
Имеет смысл только вместе с
--pathspec-from-file. Элементы спецификации путей разделяются символомNUL, а все остальные символы воспринимаются буквально (в том числе символы новой строки и кавычки). -
-U<n> -
--unified=<n> -
Создаёт различия с
<n>строками контекста. По умолчанию используетсяdiff.contextстрок контекста, а если переменная конфигурации не задана — 3 строки. (-Uбез <n> принимается без предупреждения как синоним-pиз-за исторически сложившихся причин.) -
--inter-hunk-context=<n> -
Показывает контекст между фрагментами различий, до указанного
<number>строк, объединяя тем самым близко расположенные фрагменты. По умолчанию используетсяdiff.interHunkContext, а если параметр конфигурации не задан — 0. -
-- -
Не воспринимать последующие аргументы как параметры.
- <pathspec>...
-
Ограничивает пути, затрагиваемые операцией.
Подробнее см. статью
pathspecв gitglossary[7].
Примеры
- Отмена добавления
-
$ edit (1) $ git add frotz.c filfre.c $ mailx (2) $ git reset (3) $ git pull git://info.example.com/ nitfol (4)
-
Вы довольны своей работой и считаете изменения в этих файлах удачными. Вы не хотите видеть их при запуске
gitdiff, потому что планируете работать с другими файлами, а эти изменения отвлекают. -
Кто-то просит вас выполнить pull, и изменения кажутся достойными слияния.
-
Однако вы уже изменили индекс (то есть индекс не соответствует коммиту
HEAD). Но вы знаете, что pull не затронетfrotz.cилиfilfre.c, поэтому отменяете изменения индекса для этих двух файлов. Изменения в рабочем дереве остаются. -
Теперь можно выполнить pull и merge, оставив изменения в
frotz.cиfilfre.cв рабочем дереве.
-
- Отмена и повторное создание коммита
-
$ git commit ... $ git reset --soft HEAD^ (1) $ edit (2) $ git commit -a -c ORIG_HEAD (3)
-
Так обычно поступают, если вы вспомнили, что только что созданный коммит неполон, допустили опечатку в сообщении коммита или и то и другое. Рабочее дерево остаётся в состоянии, в котором оно было до «reset».
-
Внесите исправления в файлы рабочего дерева.
-
«reset» копирует прежнюю вершину в
.git/ORIG_HEAD; повторно создайте коммит, начав с его сообщения. Если редактировать сообщение больше не нужно, вместо этого можно указать параметр-C.См. также параметр
--amendкоманды git-commit[1].
-
- Отмена коммита с созданием тематической ветки
-
$ git branch topic/wip (1) $ git reset --hard HEAD~3 (2) $ git switch topic/wip (3)
-
Вы создали несколько коммитов, но поняли, что для ветки
masterони были преждевременными. Вы хотите продолжить доводить их до совершенства в тематической ветке, поэтому создайте веткуtopic/wipот текущейHEAD. -
Перемотайте ветку master назад, чтобы удалить эти три коммита.
-
Переключитесь на ветку
topic/wipи продолжайте работу.
-
- Безвозвратная отмена коммитов
-
$ git commit ... $ git reset --hard HEAD~3 (1)
-
Последние три коммита (
HEAD,HEAD^иHEAD~2) были неудачными, и вы больше никогда не хотите их видеть. Не делайте этого, если уже передали эти коммиты кому-либо. (О последствиях см. раздел «RECOVERING FROM UPSTREAM REBASE» в git-rebase[1].)
-
- Отмена слияния или pull
-
$ git pull (1) Auto-merging nitfol CONFLICT (content): Merge conflict in nitfol Automatic merge failed; fix conflicts and then commit the result. $ git reset --hard (2) $ git pull . topic/branch (3) Updating from 41223... to 13134... Fast-forward $ git reset --hard ORIG_HEAD (4)
-
Попытка обновиться из вышестоящего репозитория привела к множеству конфликтов; вы не готовы тратить много времени на слияние прямо сейчас и решаете заняться этим позже.
-
Команда «pull» не создала коммит слияния, поэтому
gitreset--hard, являющаяся синонимомgitreset--hardHEAD, очищает файл индекса и рабочее дерево от беспорядка. -
Слейте тематическую ветку с текущей веткой; в результате произойдёт перемотка вперёд.
-
Но вы решили, что тематическая ветка ещё не готова к публикации. Команды «pull» или «merge» всегда сохраняют исходную вершину текущей ветки в
ORIG_HEAD, поэтому жёсткий сброс к ней восстанавливает прежнее состояние файла индекса и рабочего дерева, а также перемещает вершину ветки на этот коммит.
-
- Отмена слияния или pull в изменённом рабочем дереве
-
$ git pull (1) Auto-merging nitfol Merge made by recursive. nitfol | 20 +++++---- ... $ git reset --merge ORIG_HEAD (2)
-
Даже если в рабочем дереве есть локальные изменения, можно безопасно выполнить
gitpull, если вы знаете, что изменения в другой ветке с ними не пересекаются. -
Изучив результат слияния, вы можете решить, что изменения в другой ветке неудовлетворительны. Команда
gitreset--hardORIG_HEADвернёт вас к прежнему состоянию, но отбросит локальные изменения, чего вы не хотите. Командаgitreset--mergeсохранит локальные изменения.
-
- Прерванный рабочий процесс
-
Предположим, что в разгар крупного изменения вас отвлекли срочным запросом на исправление. Файлы в рабочем дереве ещё не готовы к коммиту, но вам нужно перейти в другую ветку, чтобы быстро исправить ошибку.
$ git switch feature ;# you were working in "feature" branch and $ work work work ;# got interrupted $ git commit -a -m "snapshot WIP" (1) $ git switch master $ fix fix fix $ git commit ;# commit with real log $ git switch feature $ git reset --soft HEAD^ ;# go back to WIP state (2) $ git reset (3)
-
Этот коммит будет удалён, поэтому подойдёт любое временное сообщение.
-
Команда удаляет коммит
WIPиз истории коммитов и устанавливает рабочее дерево в состояние, предшествовавшее созданию снимка. -
На этом этапе файл индекса всё ещё содержит все изменения WIP, закоммиченные вами как
snapshot WIP. Эта команда обновляет индекс, помечая файлы WIP как незафиксированные.См. также git-stash[1].
-
- Сброс одного файла в индексе
-
Предположим, что вы добавили файл в индекс, но позже решили не включать его в коммит. С помощью git reset можно удалить файл из индекса, сохранив изменения.
$ git reset -- frotz.c (1) $ git commit -m "Commit files in index" (2) $ git add frotz.c (3)
-
Удаляет файл из индекса, оставляя его в рабочем каталоге.
-
Фиксирует все остальные изменения в индексе.
-
Снова добавляет файл в индекс.
-
- Сохранение изменений в рабочем дереве при удалении некоторых предыдущих коммитов
-
Предположим, что вы работали над чем-то и создали коммит, а затем продолжили работу, но теперь считаете, что изменения в рабочем дереве должны находиться в другой ветке, не связанной с ранее созданным коммитом. Можно создать новую ветку и сбросить её, сохранив изменения в рабочем дереве.
$ git tag start $ git switch -c branch1 $ edit $ git commit ... (1) $ edit $ git switch -c branch2 (2) $ git reset --keep start (3)
-
Фиксирует первые изменения в
branch1. -
В идеальном мире вы бы поняли, что предыдущий коммит не относится к новой теме, когда создавали
branch2и переключались на неё (то естьgitswitch-cbranch2start), но никто не идеален. -
Но можно использовать
reset--keep, чтобы удалить ненужный коммит после переключения наbranch2.
-
- Разделение коммита на последовательность коммитов
-
Предположим, что вы внесли множество логически отдельных изменений и зафиксировали их одним коммитом. Позже вы решили, что лучше связать каждый логический фрагмент с отдельным коммитом. С помощью git reset можно перемотать историю назад, не изменяя содержимое локальных файлов, а затем последовательно использовать
gitadd-p, чтобы в интерактивном режиме выбирать фрагменты для включения в каждый коммит, используяgitcommit-cдля предварительного заполнения сообщения коммита.$ git reset -N HEAD^ (1) $ git add -p (2) $ git diff --cached (3) $ git commit -c HEAD@{1} (4) ... (5) $ git add ... (6) $ git diff --cached (7) $ git commit ... (8)-
Сначала перемотайте историю на один коммит назад, чтобы удалить исходный коммит, но оставить все изменения в рабочем дереве. Параметр
-Nгарантирует, что новые файлы, добавленные с помощьюHEAD, останутся помеченными таким образом, чтобы командаgitadd-pмогла их найти. -
Затем интерактивно выберите фрагменты различий для добавления с помощью функции
gitadd-p. Она последовательно предложит выбрать действие для каждого фрагмента различий: можно использовать простые команды вроде «да, включить это», «нет, не включать это» или даже очень мощную функцию «редактировать». -
Когда выберете нужные фрагменты, проверьте, что подготовлено для первого коммита, с помощью
gitdiff--cached. Команда покажет все изменения, перенесённые в индекс и готовые к фиксации. -
Затем зафиксируйте изменения, сохранённые в индексе. Параметр
-cуказывает предварительно заполнить сообщение коммита исходным сообщением, с которого вы начали работу. Это избавляет от необходимости вводить его заново.HEAD@{1}— специальное обозначение коммита, на который указывалHEADдо исходного коммита сброса (на 1 изменение раньше). Подробнее см. git-reflog[1]. Можно также использовать любую другую допустимую ссылку на коммит. -
Повторите шаги 2–4 нужное количество раз, чтобы разделить исходный код на любое количество коммитов.
-
Теперь вы выделили многие изменения в отдельные коммиты, и для выбора всех оставшихся незафиксированных изменений можно больше не использовать режим исправлений команды
gitadd. -
Ещё раз проверьте, что включили всё необходимое. Также можно убедиться, что git diff не показывает оставшихся изменений для последующей фиксации.
-
И наконец, создайте последний коммит.
-
Обсуждение
В таблицах ниже показано, что происходит при выполнении команды:
git reset --option target
для сброса HEAD на другой коммит (target) с различными параметрами сброса, в зависимости от состояния файлов.
В этих таблицах A, B, C и D обозначают различные состояния файла. Например, первая строка первой таблицы означает, что если файл находится в состоянии A в рабочем дереве, в состоянии B в индексе, в состоянии C в HEAD и в состоянии D в целевом коммите, то команда git reset --soft target оставит файл в рабочем дереве в состоянии A, а в индексе — в состоянии B. Она сбрасывает (то есть перемещает) HEAD (то есть вершину текущей ветки, если вы находитесь в ней) на target (в котором файл находится в состоянии D).
working index HEAD target working index HEAD
----------------------------------------------------
A B C D --soft A B D
--mixed A D D
--hard D D D
--merge (disallowed)
--keep (disallowed) working index HEAD target working index HEAD
----------------------------------------------------
A B C C --soft A B C
--mixed A C C
--hard C C C
--merge (disallowed)
--keep A C C working index HEAD target working index HEAD
----------------------------------------------------
B B C D --soft B B D
--mixed B D D
--hard D D D
--merge D D D
--keep (disallowed) working index HEAD target working index HEAD
----------------------------------------------------
B B C C --soft B B C
--mixed B C C
--hard C C C
--merge C C C
--keep B C C working index HEAD target working index HEAD
----------------------------------------------------
B C C D --soft B C D
--mixed B D D
--hard D D D
--merge (disallowed)
--keep (disallowed) working index HEAD target working index HEAD
----------------------------------------------------
B C C C --soft B C C
--mixed B C C
--hard C C C
--merge B C C
--keep B C C git reset --merge предназначена для сброса после конфликтующего слияния. Любая операция слияния гарантирует, что до её начала файл рабочего дерева, участвующий в слиянии, не содержит локальных изменений относительно индекса, и что результат записывается в рабочее дерево. Поэтому, если мы видим различия между индексом и целевым коммитом, а также между индексом и рабочим деревом, значит, сброс выполняется не из состояния, оставшегося после неудачной операции слияния с конфликтом. Поэтому в этом случае мы запрещаем параметр --merge.
git reset --keep предназначена для удаления нескольких последних коммитов текущей ветки с сохранением изменений в рабочем дереве. Если между изменениями в удаляемом коммите и изменениями рабочего дерева, которые нужно сохранить, могут возникнуть конфликты, сброс запрещается. Поэтому он запрещён, если имеются изменения как между рабочим деревом и HEAD, так и между HEAD и целевым коммитом. В целях безопасности сброс также запрещён при наличии неслитых записей.
В следующих таблицах показано, что происходит при наличии неслитых записей:
working index HEAD target working index HEAD
----------------------------------------------------
X U A B --soft (disallowed)
--mixed X B B
--hard B B B
--merge B B B
--keep (disallowed) working index HEAD target working index HEAD
----------------------------------------------------
X U A A --soft (disallowed)
--mixed X A A
--hard A A A
--merge A A A
--keep (disallowed) X означает любое состояние, а U — неслитый индекс.
reset
© 2005–2026 Linus Torvalds and others
Licensed under the GNU General Public License version 2.
https://git-scm.com/docs/git-reset