В чем разница между git reset --hard HEAD ~ 1 и git reset --soft HEAD ~ 1?


Ответы:


184

git resetзнает пять «режимов»: мягкий, смешанный, жесткий, слияние и сохранение. Я начну с первых трех, так как с этими режимами вы обычно сталкиваетесь. После этого вы найдете приятный небольшой бонус, так что следите за обновлениями.

мягкий

При использовании git reset --soft HEAD~1вы удалите последнюю фиксацию из текущей ветки, но изменения файла останутся в вашем рабочем дереве . Также изменения останутся в вашем индексе, поэтому послеgit commit будет создана фиксация с теми же изменениями, что и фиксация, которую вы «удалили» ранее.

смешанный

Это режим по умолчанию, очень похожий на мягкий. При «удалении» коммита git reset HEAD~1вы все равно сохраните изменения в вашем рабочем дереве, но не в индексе; поэтому, если вы хотите «повторить» фиксацию, вам нужно будет добавить changes ( git add) перед фиксацией.

жесткий

При использовании git reset --hard HEAD~1вы потеряете все незавершенные изменения в дополнение к изменениям, внесенным в последний коммит. Изменения не останутся в вашем рабочем дереве, поэтому выполнение git statusкоманды сообщит вам, что в вашем репозитории нет изменений.

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

Бонус

хранить

git reset --keep HEAD~1интересный и полезный. Он только сбрасывает файлы, которые отличаются между текущим HEAD и данным коммитом. Он прерывает сброс, если в каком-либо из этих файлов есть незавершенные изменения. По сути, он действует как более безопасная версия hard.

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


Вы можете узнать больше об этом в документации по git reset .

Примечание.
При git resetудалении фиксации фиксация на самом деле не теряется, просто нет ссылки, указывающей на нее или любого из ее дочерних элементов. Вы все еще можете восстановить коммит, который был «удален» с git resetпомощью поиска его ключа SHA-1, например, с помощью такой команды, как git reflog.


1
Я не согласен с тем, что мы обычно должны использовать именно эти 3. Это те 3, которые были доступны впервые, поэтому люди говорят об этих 3 больше, но --hardэто почти никогда не является правильным --keepрешением , так как намного безопаснее и применимо к большинству сенариев, где --hardработает. --keepКогда-нибудь тренировка пальцев может спасти вас ...
Матье Мой

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

Чтобы добавить немного больше деталей, после git reset --soft HEAD ~ 1, используя git commit --reuse-message = HEAD @ {1}, чтобы повторно использовать последнюю фиксацию с сохраненным старым индексом, как показано здесь stackoverflow.com/a/ 25930432/2883282
englealuze

3
@MatthieuMoy, на три года позже, но я добавил раздел keep. ;)
Sascha Wolf

Как я могу отменить последнюю фиксацию? Пожалуйста помоги. Если я использую git reset --soft HEAD ~ 1, я получаю: фатальный: неоднозначный аргумент «HEAD ~ 1»: неизвестная версия или путь не в рабочем дереве. Используйте '-' для отделения путей от ревизий, например: 'git <command> [<revision> ...] - [<file> ...]'
elvis

8

Git reset имеет 5 основных режимов: мягкий, смешанный, объединенный, жесткий, сохранить . Разница между ними - менять или не менять заголовок, этап (индекс), рабочий каталог .

Git reset --hard изменит заголовок, индекс и рабочий каталог.
Git reset --soft изменит только голову. Без изменений в индексе, рабочем каталоге.

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

С параметром --hard вы полностью получите свой проект с чистого листа. Как будто с последней фиксации не было никаких изменений. Если вы уверены, что это то, чего хотите, двигайтесь вперед. Но как только вы это сделаете, вы полностью потеряете свой последний коммит. (Примечание: есть еще способы восстановить потерянную фиксацию).


5

Это полезная статья, в которой графически показано объяснение команды сброса.

https://git-scm.com/docs/git-reset

Reset --hard может быть довольно опасным, поскольку он перезаписывает вашу рабочую копию без проверки, поэтому, если вы вообще не зафиксировали файл, он исчезнет.

Что касается дерева исходного кода, я не знаю способа отменить коммиты. Скорее всего, он все равно использовал бы сброс под крышкой


+1 за ссылку на официальную документацию. Я бы также упомянул, git reset --helpчто довольно хорошо объясняет (на мой взгляд) пять режимов или, по крайней мере, два, запрошенные OP.
ThanksForAllTheFish 04

1
Ссылка не работает. Скорее всего, это текущая версия: git-scm.com/docs/git-reset
Кики Джуэлл

1

Это основное различие между использованием git reset --hard и git reset --soft:

--soft

Не затрагивает индексный файл или рабочее дерево (но сбрасывает заголовок, как и все режимы). Это оставляет все ваши измененные файлы «Изменения должны быть зафиксированы», как сказал бы git status.

--hard

Сбрасывает индекс и рабочее дерево. Любые изменения отслеживаемых файлов в рабочем дереве с тех пор отменяются.


1
Это то, что я искал. Кратко и точно.
Qasim
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.