В чем разница между Git Revert, Checkout и Reset?

276

Я пытаюсь узнать , как восстановить или откат файлов и проекты в предыдущее состояние, и не понимает разницы между git revert, checkoutи reset. Почему существуют три разные команды для одной и той же цели, и когда кто-то должен выбирать одну над другой?

haziz
источник

Ответы:

462

Эти три команды имеют совершенно разные цели. Они даже отдаленно не похожи.

git revert

Эта команда создает новый коммит, который отменяет изменения предыдущего коммита. Эта команда добавляет новую историю в проект (она не изменяет существующую историю).

git checkout

Эта команда извлекает содержимое из репозитория и помещает его в дерево работы. Это также может иметь другие эффекты, в зависимости от того, как была вызвана команда. Например, он также может изменить ветку, над которой вы сейчас работаете. Эта команда не вносит никаких изменений в историю.

git reset

Эта команда немного сложнее. Это на самом деле делает несколько разных вещей в зависимости от того, как он вызывается. Он изменяет индекс (так называемая «область подготовки»). Или это меняет то, на какой коммит в данный момент указывает голова ветки. Эта команда может изменить существующую историю (путем изменения коммита, на который ссылается ветка).

Используя эти команды

Если коммит был сделан где-то в истории проекта, и вы позже решили, что коммит был неправильным и не должен был быть сделан, тогда git revertэто инструмент для работы. Он отменит изменения, внесенные плохим коммитом, записав «отмену» в истории.

Если вы изменили файл в своем рабочем дереве, но не зафиксировали это изменение, вы можете использовать git checkoutдля извлечения свежую копию файла из хранилища.

Если вы сделали коммит, но не поделились им с кем-либо еще и решили, что он вам не нужен, то вы можете git resetпереписать историю так, чтобы она выглядела так, как будто вы никогда не делали этот коммит.

Это лишь некоторые из возможных сценариев использования. Существуют и другие команды, которые могут быть полезны в некоторых ситуациях, и у вышеперечисленных трех команд есть и другие применения.

Дэн Молдинг
источник
13
Таким образом, эти три команды могут использоваться для ОТМЕНЫ некоторой работы, что означает, что они не настолько «совершенно разные». Та же концепция, разные контексты.
Бруно Сантос
16
@BrunoSantos: подсвечники, свинцовые трубы, кинжалы и веревки могут быть использованы для убийства людей, но это не значит, что какие-либо из этих вещей особенно похожи.
Дэн Молдинг
12
@Dan Mounlding - На самом деле, есть много случаев, когда git resetи git checkoutможно сделать одно и то же. Сказать, что они «даже отдаленно не похожи», - это не просто преувеличение: это даже отдаленно не верно. Эти две команды могут делать очень много разных вещей, некоторые из которых полностью перекрываются. Пример: git reset --hardи git checkout -- .будет делать то же самое. И, по логике, git reset --hard <path>и git checkout <path>должен делать то же самое - git однако мешает вам это сделать. Путать эти две команды очень легко.
ДанГордон
5
@ DanGordon Я понимаю, что у нас, вероятно, просто будет другое мнение. Тем не менее, я чувствую, что должен дать какое-то объяснение. Вы не можете делать то, git reset --hard <path>что можете, git checkout <path>именно потому, что две команды делают что-то совершенно другое. git resetговорит Git переместить HEAD на другой коммит. git checkoutс другой стороны, Git вообще не просит ничего делать с HEAD. Он оставляет HEAD один и просто проверяет файл. Да, вы можете создать их таким образом, чтобы они имели схожие эффекты. Но то, что они на самом деле делают , совершенно другое.
Дэн Молдинг
47

Допустим, у вас были коммиты:

C
B
A

git revert B, создаст коммит, который отменяет изменения в B.

git revert A, создаст коммит, который отменяет изменения в A, но не затрагивает изменения вB

Обратите внимание, что если изменения в Bзависимости от изменений в A, отмена Aневозможна.

git reset --soft A, изменит историю коммитов и репозиторий; промежуточный и рабочий каталог все еще будет в состоянии C.

git reset --mixed A, изменит историю коммитов, репозиторий и этапы; рабочий каталог все еще будет в состоянии C.

git reset --hard A, изменит историю коммитов, репозиторий, промежуточный и рабочий каталог; Вы вернетесь в состояние Aполностью.

Akavall
источник
1
Такой интуитивный ответ .. как насчет оформления
MJ Studio
29
  • git revertиспользуется для отмены предыдущего коммита. В git вы не можете изменить или стереть предыдущий коммит. (На самом деле вы можете, но это может вызвать проблемы.) Таким образом, вместо редактирования более раннего коммита, возврат вводит новый коммит, который переворачивает более ранний.
  • git reset используется для отмены изменений в вашем рабочем каталоге, которые еще не были добавлены
  • git checkoutиспользуется для копирования файла из какого-либо другого коммита в ваше текущее рабочее дерево. Он не фиксирует файл автоматически.
Джонатан
источник
7
Я полагаю, что вы ошибаетесь насчет "git reset". "git reset" сбрасывает ваш HEAD к одному из предыдущих коммитов, он не сбрасывает ваш рабочий каталог. Рабочий каталог «сбрасывается» с помощью «git checkout [filename]»
luigi7up
11
git reset --softсбрасывает только заголовок, git reset --hardсбрасывает заголовок и ваш рабочий каталог.
Ehryk
git reset --mixed (по умолчанию): uncommit + нестабильные изменения
NattyC
21
  • git checkout изменяет ваше рабочее дерево,
  • git reset изменяет ссылку на ветвь, на которую вы указываете,
  • git revert добавляет фиксацию отмены изменений.
dan_waterworth
источник
4
git reset не просто изменяет коммит, на который указывает ветвь , он также используется для удаления файлов из индекса и может изменять рабочую копию git reset --mixed(по умолчанию).
git reset --soft: отменить изменения, изменения оставлены поэтапными (индекс). git reset --mixed (по умолчанию): uncommit + нестабильные изменения, изменения остаются в рабочем дереве. git reset --hard: uncommit + unstage + удалить изменения, ничего не осталось.
NattyC
6

Сброс - на уровне фиксации сброс - это способ переместить верхушку ветви на другой коммит. Это может быть использовано для удаления коммитов из текущей ветви.

Revert - Откат Отменяет коммит путем создания нового коммита. Это безопасный способ отменить изменения, поскольку у него нет шансов переписать историю коммитов. Сравните это с git reset, который изменяет существующую историю коммитов. По этой причине следует использовать git revert для отмены изменений в публичной ветке, а git reset следует зарезервировать для отмены изменений в частной ветке.

Вы можете посмотреть по этой ссылке - Сбросить, Оформить заказ и Восстановить

Саччидананд Сингх
источник
5

Если вы сломали дерево, но не зафиксировали код, вы можете использовать git reset, и если вы просто хотите восстановить один файл, вы можете использовать git checkout.

Если вы сломали дерево и зафиксировали код, вы можете использовать git revert HEAD.

http://book.git-scm.com/4_undoing_in_git_-_reset,_checkout_and_revert.html

LostMohican
источник