В чём отличие `git reset`, `git checkout`, `git restore`?

git reset: Перемещает указатель ветки (HEAD) на указанный коммит. Может изменять индекс (staging area) и рабочий каталог в зависимости от типа (--soft, --mixed, --hard). Используется для отмены коммитов (локально!).

git checkout: Основная задача - переключение между ветками. Также может использоваться для восстановления файлов из индекса или коммитов. Обновляет рабочий каталог в соответствии с выбранной веткой или коммитом.

git restore: Более специализированная команда, добавленная в Git 2.23, предназначенная для отмены изменений в рабочем каталоге и/или индексе. В отличие от git checkout, она фокусируется на восстановлении файлов, а не на переключении веток.


Отличия между git reset, git checkout и git restore заключаются в их влиянии на рабочую директорию, индекс (staging area) и историю коммитов. Они используются для отмены изменений, но каждый в разной степени и разными способами.

git reset:

  • Изменяет указатель HEAD и, опционально, индекс и рабочую директорию.
  • Доступны три основных режима: --soft, --mixed (по умолчанию) и --hard.
  • --soft: Перемещает HEAD на указанный коммит, оставляя индекс и рабочую директорию без изменений. Изменения, сделанные после этого коммита, останутся в вашей рабочей области как зафиксированные изменения.
  • --mixed: Перемещает HEAD на указанный коммит и сбрасывает индекс, но оставляет рабочую директорию без изменений. Изменения, сделанные после этого коммита, останутся в вашей рабочей области, но не будут добавлены для коммита (unstaged). Это наиболее часто используемый вариант.
  • --hard: Перемещает HEAD на указанный коммит, сбрасывает индекс и рабочую директорию. ОСТОРОЖНО! Все изменения, сделанные после указанного коммита, будут ПОТЕРЯНЫ. Используйте этот режим с большой осторожностью.
  • В основном используется для отмены локальных коммитов, а также для перемещения ветки назад во времени.
  • Влияет на историю коммитов (в локальном репозитории). При выполнении git push после git reset может потребоваться git push --force, что не рекомендуется делать в общих ветках.

git checkout:

  • В основном используется для переключения между ветками.
  • Также можно использовать для восстановления отдельных файлов из определенного коммита, но это устаревший способ (смотрите git restore).
  • При переключении между ветками git checkout обновляет рабочую директорию и индекс в соответствии с коммитом, на который указывает HEAD выбранной ветки.
  • git checkout <commit> <file>: восстанавливает файл из указанного коммита, помещая его в индекс и рабочую директорию. (устаревший синтаксис, лучше использовать git restore)
  • Влияет на рабочую директорию и индекс, но не изменяет историю коммитов.
  • Создает detached HEAD при переходе на конкретный коммит (не на ветку).

git restore:

  • Предназначен для отмены изменений в рабочей директории и индексе.
  • Является более современным и понятным способом отмены изменений, чем git checkout для отдельных файлов.
  • git restore <file>: Отменяет изменения в рабочей директории, возвращая файл к состоянию из индекса.
  • git restore --staged <file>: Удаляет файл из индекса, перемещая изменения в рабочую директорию (unstaged).
  • git restore --source=<commit> <file>: Восстанавливает файл из указанного коммита в рабочей директории.
  • Влияет только на рабочую директорию и индекс, не изменяет историю коммитов.

Краткое сравнение:

  • git reset: Изменяет HEAD, индекс и рабочую директорию. Может изменять историю коммитов.
  • git checkout: Переключается между ветками, либо восстанавливает файлы из конкретного коммита (но это устаревший синтаксис, сейчас лучше использовать git restore). Не изменяет историю коммитов.
  • git restore: Предназначен для отмены изменений в рабочей директории и индексе. Не изменяет историю коммитов. Заменяет часть функциональности git checkout.

Когда что использовать:

  • git reset: Когда нужно откатить локальные коммиты.
  • git checkout: Когда нужно переключиться между ветками или посмотреть старую версию проекта в режиме detached HEAD.
  • git restore: Когда нужно отменить изменения в рабочей директории или убрать файлы из индекса.

0