Какая разница между git reset --mixed, --soft и --hard?
Я хочу разделить фиксацию и не уверен, какой вариант reset использовать.
Я смотрел страницу Можете ли вы объяснить, что такое git reset " делает на простом английском?, но я понял, что не понимаю, что такое индекс или область размещения git, и поэтому объяснения не помогли.
Также варианты использования для --mixed
и --soft
выглядят одинаково для меня в этом ответе (когда вы хотите исправить и подтвердить.) Может ли кто-то сломать его еще больше? Я понимаю, что --mixed
, вероятно, вариант, но я хочу знать, почему. Наконец, что насчет --hard
?
Может ли кто-нибудь дать мне пример рабочего процесса, как выбрать 3 варианта?
Ответы
Ответ 1
Когда вы изменяете файл в своем репозитории, изменение первоначально не выполняется. Чтобы зафиксировать это, вы должны выполнить его, то есть добавить его в индекс-используя git add
. Когда вы совершаете фиксацию, те изменения, которые были добавлены в индекс, были внесены в индекс.
git reset
изменяет, как минимум, текущую ветвь (HEAD
). Разница между --mixed
и --soft
заключается в том, изменен ли ваш индекс. Итак, если мы находимся на ветке master
с этой серией коммитов:
- A - B - C (master)
HEAD
указывает на C
, а индекс соответствует C
.
Когда мы запускаем git reset --soft B
, master
(и, следовательно, HEAD
) теперь указывает на B
, но индекс все еще имеет изменения от C
; git status
покажет их как поставленные. Поэтому, если в этот момент мы запустим git commit
, мы получим новый коммит с теми же изменениями, что и C
.
Хорошо, так, начиная снова здесь:
- A - B - C (master)
Теперь давайте сделаем git reset --mixed B
. (Примечание: --mixed
- опция по умолчанию). Еще раз, master
и HEAD
указывают на B, но на этот раз индекс также изменяется в соответствии с B
. Если в этот момент мы запустим git commit
, ничего не произойдет, так как индекс соответствует HEAD
. У нас все еще есть изменения в рабочем каталоге, но поскольку они не находятся в индексе, git status
показывает их как нестационарные. Чтобы зафиксировать их, вы должны были бы git add
и затем выполнить как обычно.
И, наконец, --hard
совпадает с --mixed
(он изменяет ваш HEAD
и индекс), за исключением того, что --hard
также изменяет ваш рабочий каталог. Если мы находимся в C
и запустим git reset --hard B
, то изменения, добавленные в C
, а также любые незафиксированные вами изменения будут удалены, а файлы в вашей рабочей копии будут соответствовать commit B
. Поскольку вы можете навсегда потерять изменения таким образом, вы должны всегда запускать git status
, прежде чем делать жесткий reset, чтобы убедиться, что ваш рабочий каталог чист или что вы в порядке с потерей ваших незафиксированных изменений.
И, наконец, визуализация:
![enter image description here]()
Ответ 2
Проще говоря:
-
--soft
: незафиксированные изменения, изменения оставляются поэтапными (индекс). -
--mixed
(по умолчанию): uncommit + unstage изменения, изменения остаются в рабочем дереве. -
--hard
: uncommit + unstage + удалить изменения, ничего не осталось.
Ответ 3
Помните, что это упрощенное объяснение, предназначенное для первого этапа поиска этой сложной функциональности.
Может быть полезно для зрителей, которые хотят визуализировать, как выглядит их состояние проекта после каждой из этих команд:
Для тех, кто использует терминал с включенным цветом
(git config --global color.ui auto):
git reset --soft A
, и вы увидите, что элементы B и C зеленые (поставлены и готовы к фиксации)
git reset --mixed A
(или git reset A
), и вы увидите элементы B и C в красном (нестационарные и готовые к постановке (зеленый), а затем завершенные)
git reset --hard A
, и вы больше не увидите изменений B и C в любом месте (будет, как если бы они никогда не существовали)
Или для тех, кто использует программу GUI, например "Tower" или "SourceTree"
git reset --soft A
, и вы увидите, что элементы B и C в области "поставленные файлы" готовы к фиксации
git reset --mixed A
(или git reset A
), и вы увидите элементы B и C в области "неустановленные файлы", готовые к поэтапному перемещению, а затем зафиксированные
git reset --hard A
, и вы больше не увидите изменений B и C в любом месте (будет, как если бы они никогда не существовали)
Ответ 4
Вот базовое объяснение для пользователей TortoiseGit:
git reset --soft
и --mixed
оставить ваши файлы нетронутыми.
git reset --hard
действительно измените свои файлы в соответствии с фиксацией, которую вы reset на.
В TortoiseGit, концепция индекса очень скрыта графическим интерфейсом. При изменении файла вам не нужно запускать git add
, чтобы добавить изменения в промежуточную область/индекс. При простом изменении существующих файлов, не изменяющих имена файлов, git reset --soft
и --mixed
одинаковы! Вы заметите разницу, если вы добавили новые файлы или переименовали файлы. В этом случае, если вы запустите git reset --mixed, вам придется повторно добавить файл из списка Неверяемые файлы.
Ответ 5
В этих случаях мне нравится визуал, который, я надеюсь, может объяснить это:
git reset --[hard/mixed/soft]
:
![enter image description here]()
Так что у каждого эффекта разные рамки
- Hard => WorkingDir + Index + HEAD
- Смешанный => Индекс + ГОЛОВА
- Soft => HEAD only (индекс и рабочий каталог без изменений).
Ответ 6
Все остальные ответы великолепны, но я считаю, что лучше всего их понять, разбив файлы на три категории: unstaged
, staged
, commit
:
-
--hard
должно быть легко понять, оно восстанавливает все -
--mixed
(по умолчанию): -
unstaged
файлы: не меняйте -
staged
файлы: перейти к unstaged
-
commit
файлы: переместить в unstaged
-
--soft
: -
unstaged
файлы: не меняйте -
staged
файлы: не меняйте -
commit
файлы: перейти к staged
В итоге:
-
--soft
переместит все (кроме unstaged
файлов) в staging area
-
--mixed
переместит все в unstaged area
Ответ 7
Прежде чем перейти к этим трем вариантам, нужно понимать три вещи.
1) История /HEAD
2) Этап/индекс
3) Рабочий каталог
reset --soft: изменилась история, изменен HEAD, рабочий каталог не изменен.
reset --mixed: изменена история, изменен HEAD, рабочий каталог изменен с неустановленными данными.
reset --hard: история изменена, HEAD изменен, рабочий каталог изменен с потерянными данными.
Всегда безопасно работать с Git --soft. В сложном требовании следует использовать другой вариант.
Ответ 8
Вам не нужно заставлять себя помнить различия между ними. Подумайте, как вы на самом деле сделали коммит.
1. Внесите некоторые изменения.
2.git добавить.
3.gc -m "Я что-то сделал"
Soft, Mixed и Hard - это способ, позволяющий отказаться от операций, которые вы делали от 3 до 1.
Софт "сделал вид", чтобы никогда не видеть, что вы сделали "gc -m".
Смешанный "сделал вид", чтобы никогда не видеть, что вы сделали "git add".
Тяжело "притворялся", чтобы никогда не видеть, что вы сделали изменения в файле.
Ответ 9
Короткий ответ, в каком контексте используются 3 варианта:
Чтобы сохранить текущие изменения в коде, но переписать историю фиксации:
-
soft
: вы можете совершить все сразу и создать новый коммит с новым описанием (если вы используете torotise git или любые другие графические интерфейсы, это тот, который вы используете, так как вы можете пометить, какие файлы вы хотите в фиксации и сделать несколько коммитов таким образом с разными файлами. В Sourcetree все файлы будут поставлены для фиксации.)
-
mixed
: вам нужно будет добавить отдельные файлы снова в индекс, прежде чем совершать коммиты (в Sourcetree все измененные файлы будут неактивными)
На самом деле потерять изменения в коде:
-
hard
: вы не просто переписываете историю, но также теряете все свои изменения вплоть до того, что вы reset
Ответ 10
Основное различие между различными опциями команды git reset приведено ниже.
- --soft: Сбрасывает только HEAD в выбранный вами коммит. Работает в основном так же, как git checkout, но не создает отдельное состояние головы.
- --mixed (опция по умолчанию): сбрасывает заголовок в фиксацию, выбранную вами в истории, и отменяет изменения в индексе.
- --hard: сбрасывает заголовок в коммит, выбранный вами в истории, отменяет изменения в индексе и отменяет изменения в вашем рабочем каталоге.
Ответ 11
--soft
: Говорит Git сбросить HEAD для другого коммита, поэтому индекс и рабочий каталог не будут изменены каким-либо образом. Все файлы, измененные между оригинальным HEAD и коммитом, будут размещены.
--mixed
: Так же, как и софт, это сбросит HEAD к другому коммиту. Он также сбросит индекс, чтобы он соответствовал ему, в то время как рабочий каталог не будет затронут. Все изменения останутся в рабочем каталоге и появятся как измененные, но не подготовленные.
--hard
: Это сбрасывает все - он сбрасывает HEAD обратно в другой коммит, сбрасывает индекс, чтобы соответствовать ему, и сбрасывает рабочий каталог, чтобы соответствовать ему.
Основное различие между --mixed
и --soft
заключается в том, --soft
или нет ваш индекс. Проверьте больше об этом здесь.
Ответ 12
Здесь есть несколько ответов с неправильным представлением о git reset --soft
. Хотя есть определенное условие, при котором git reset --soft
изменит только HEAD
(начиная с состояния отсоединенной головки), обычно (и для предполагаемого использования), он перемещает ссылку ветвления, которую вы в настоящее время извлекли. Конечно, это не может быть сделано, если у вас нет проверенной ветки (отсюда определенное условие, при котором git reset --soft
только изменит HEAD
).
Я обнаружил, что это лучший способ думать о git reset
. Вы не просто двигаете HEAD
(все это делает), вы также перемещаете ссылку на ветку, например, master
. Это похоже на то, что происходит, когда вы запускаете git commit
(текущая ветвь перемещается вместе с HEAD
), за исключением того, что вместо создания (и перехода к) новой фиксации вы переходите к предыдущей фиксации.
Это точка reset
, изменение ветки на что-то другое, чем новый коммит, а не изменение HEAD
. Вы можете увидеть это в примере документации:
Отменить коммит, сделав его веткой тем
$ git branch topic/wip (1)
$ git reset --hard HEAD~3 (2)
$ git checkout topic/wip (3)
- Вы сделали некоторые коммиты, но понимаете, что они были преждевременны, чтобы быть в "основной" ветке. Вы хотите продолжить полировать их в ветке темы, поэтому создайте ветку "topic/wip" вне текущего заголовка.
- Перемотайте ветку master, чтобы избавиться от этих трех коммитов.
- Переключитесь на ветку "topic/wip" и продолжайте работать.
Какой смысл в этой серии команд? Вы хотите переместить ветку, здесь master
, так что, пока master
извлечен, вы запускаете git reset
.
Ответ с наибольшим количеством голосов здесь в целом хорош, но я подумал, что добавлю это, чтобы исправить несколько ответов с ошибочными представлениями.
Измени свою ветку
git reset --soft <ref>
: сбрасывает указатель ветки для текущей извлеченной ветки в фиксацию по указанной ссылке git reset --soft <ref>
Файлы в вашем рабочем каталоге и индексе не изменены. Фиксация с этого этапа вернет вас туда, где вы были до команды git reset
.
Измените свой индекс тоже
git reset --mixed <ref>
или эквивалентно
git reset <ref>
:
Делает то, что делает --soft
И также сбрасывает индекс в соответствии с фиксацией по указанной ссылке. В то время как git reset --soft HEAD
ничего не делает (потому что говорит, что перемещает извлеченную ветвь в извлеченную ветвь), git reset --mixed HEAD
, или эквивалентно git reset HEAD
, является распространенной и полезной командой, потому что она сбрасывает индекс в состояние вашего последнего коммита.
Измените свой рабочий каталог тоже
git reset --hard <ref>
: делает то, что делает --mixed
И также перезаписывает ваш рабочий каталог. Эта команда похожа на git checkout <ref>
, за исключением того, что (и это критический момент для reset
) все формы git reset
перемещают ветку ref, на которую указывает ссылка HEAD
.
Примечание о "такая-то команда перемещает ГОЛОВУ":
Бесполезно говорить, что команда перемещает HEAD
. Любая команда, которая меняет ваше местоположение в истории коммитов, перемещает HEAD
. То, что HEAD
есть указатель, где вы находитесь. HEAD
- это вы, и поэтому будете двигаться, когда вы это делаете.
Ответ 13
mkarasek Ответ отличный, простыми словами мы можем сказать...
-
git reset --soft
: установите для HEAD
значение предполагаемого коммита, но сохраняйте изменения, git reset --soft
с момента последнего коммита -
git reset --mixed
: то же самое, что git reset --soft
но единственное отличие состоит в том, что он не git reset --soft
ваши изменения после последних коммитов -
git reset --hard
: установите HEAD
на указанный вами коммит и сбросьте все ваши изменения с последних коммитов, включая не зафиксированные.