Какая разница между 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

Так что у каждого эффекта разные рамки

  1. Hard => WorkingDir + Index + HEAD
  2. Смешанный => Индекс + ГОЛОВА
  3. Soft => HEAD only (индекс и рабочий каталог без изменений).

Ответ 6

Все остальные ответы великолепны, но я считаю, что лучше всего их понять, разбив файлы на три категории: unstaged, staged, commit:

  • --hard должно быть легко понять, оно восстанавливает все
  • --mixed (по умолчанию):
    1. unstaged файлы: не меняйте
    2. staged файлы: перейти к unstaged
    3. commit файлы: переместить в unstaged
  • --soft:
    1. unstaged файлы: не меняйте
    2. staged файлы: не меняйте
    3. 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)
  1. Вы сделали некоторые коммиты, но понимаете, что они были преждевременны, чтобы быть в "основной" ветке. Вы хотите продолжить полировать их в ветке темы, поэтому создайте ветку "topic/wip" вне текущего заголовка.
  2. Перемотайте ветку master, чтобы избавиться от этих трех коммитов.
  3. Переключитесь на ветку "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 на указанный вами коммит и сбросьте все ваши изменения с последних коммитов, включая не зафиксированные.