В чем разница между git reset --mixed, --soft и --hard? - PullRequest
636 голосов
/ 20 августа 2010

Я хочу разделить коммит и не уверен, какой вариант сброса использовать.

Я смотрел на страницу Можете ли вы объяснить, что делает "git reset" на простом английском? , но я понял, что не совсем понимаю, что такое индекс git или область подготовки и, следовательно, объяснения не помогло.

Кроме того, варианты использования для --mixed и --soft выглядят одинаково для меня в этом ответе (когда вы хотите исправить и подтвердить.) Может кто-нибудь разбить его еще больше? Я понимаю, что --mixed, вероятно, вариант, но я хочу знать, , почему . Наконец, как насчет --hard?

Может ли кто-нибудь дать мне пример рабочего процесса того, как будет происходить выбор трех вариантов?

Ответы [ 13 ]

1291 голосов
/ 20 августа 2010

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

git reset изменения, как минимум, на которые указывает текущая ветвь (HEAD).Разница между --mixed и --soft заключается в том, изменен или нет ваш индекс.Итак, если мы находимся на ветке master с этой серией коммитов:

- A - B - C (master)

HEAD указывает на C, а индекс соответствует C.

Когда мыrun 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, а также любые незафиксированные изменения, которые у вас есть, будут удалены, и файлы в вашей рабочей копии будут соответствовать коммиту B.Поскольку вы можете навсегда потерять изменения таким образом, вы должны всегда запускать git status перед выполнением аппаратного сброса, чтобы убедиться, что ваш рабочий каталог чист или что вы в порядке потери ваших незафиксированных изменений.


И наконец, визуализация: enter image description here

86 голосов
/ 25 апреля 2018

Проще говоря:

  • --soft: uncommit изменения, изменения остаются поэтапными ( index ).
  • --mixed (по умолчанию) : uncommit + unstage изменения, изменения остаются в рабочем дереве .
  • --hard: uncommit + unstage + delete изменения, ничего не осталось.
67 голосов
/ 21 ноября 2014

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

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


Для тех, кто использует Терминал с включенным цветом (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 (как если бы они никогда не существовали)


или для тех, кто использует программу с графическим интерфейсомнапример, 'Tower' или 'SourceTree'

git reset --soft A, и вы увидите вещи B и C в области 'staged files', готовые к фиксации

git reset --mixed A (или git reset A)и вы увидите вещи B и C в области 'unstaged files', готовые для bОн перешел в инсценировку, а затем совершил

git reset --hard A, и вы больше нигде не увидите изменений B и C (как если бы они никогда не существовали)

21 голосов
/ 28 октября 2014

Вот базовое объяснение для пользователей TortoiseGit:

git reset --soft и --mixed оставьте ваши файлы без изменений.

git reset --hard на самом деле измените ваши файлы в соответствии с коммитом, к которому вы сбросили.

В TortoiseGit концепция индекса очень скрытапо GUI.Когда вы изменяете файл, вам не нужно запускать git add, чтобы добавить изменение в промежуточную область / индекс.При работе с изменениями существующих файлов, которые не меняют имен файлов, git reset --soft и --mixed одинаковы!Вы заметите разницу только в том случае, если добавите новые или переименованные файлы.В этом случае, если вы запустите git reset --mixed, вам придется повторно добавить ваши файлы из списка Not Versioned Files .

11 голосов
/ 13 сентября 2018

В этих случаях мне нравится визуальный эффект, который, мы надеемся, может объяснить это:

git reset --[hard/mixed/soft]:

enter image description here

Таким образом, каждый эффектразличные области действия

  1. Hard => WorkingDir + Index + HEAD
  2. Mixed => Index + HEAD
  3. Soft => Только HEAD (индекс и рабочий каталог без изменений).
4 голосов
/ 14 ноября 2017

Прежде чем перейти к этим трем вариантам, нужно понять 3 вещи.

1) История / ГОЛОВА

2) Стадия / индекс

3) Рабочий каталог

сброс --soft: история изменена, заголовок изменен, рабочий каталог не изменен.

reset --mixed: история изменена, HEAD изменена, рабочая папка изменена с неподготовленными данными.

сброс --hard: история изменена, HEAD изменен, рабочий каталог изменен с потерянными данными.

С Git --soft всегда безопасно. Нужно использовать другой вариант в сложном требовании.

2 голосов
/ 14 декабря 2018

Вам не нужно заставлять себя помнить различия между ними. Подумайте, как вы на самом деле сделали коммит.

1.Внесите некоторые изменения.

2.git add.

3.gc -m "Я что-то сделал"

Soft, Mixed и Hard - это способ, позволяющий отказаться от операций, которые вы выполняли с 3 до 1.

Софт "сделал вид", что никогда не видел, что вы сделали "gc -m".

Смешанный «притворялся», чтобы никогда не видеть, что вы сделали «git add».

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

1 голос
/ 15 июня 2019

Все остальные ответы великолепны, но я считаю, что лучше понять их, разбив файлы на три категории: 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
1 голос
/ 01 марта 2019

Здесь есть несколько ответов с неправильным представлением о git reset --soft.В то время как есть определенное условие, при котором git reset --soft изменит только HEAD (начиная с состояния отсоединенной головки), обычно (и для предполагаемого использования), перемещает ссылку ветвления, которую вы в настоящее время извлекли. Конечно, это не может быть сделано, если вы не отметили ветку (отсюда определенное условие, где git reset --soft изменит только HEAD).

Я считаю, что это лучший способ думать о git reset.Вы не просто двигаете HEAD ( все делает это ), вы также перемещаете ref ref ответвления, например, 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" вне текущей HEAD.
  2. Перемотайте ветку master, чтобы избавиться от этих трех коммитов.
  3. Switchв ветку "topic / wip" и продолжайте работать.

Какой смысл этой серии команд?Вы хотите переместить ветку , здесь master, поэтому, пока вы master извлечены, вы запускаете git reset.

Ответ с верхним голосом здесь, как правило, хорош, ноЯ подумал, что добавлю это, чтобы исправить несколько ответов с ошибочными представлениями.

Изменить ветку

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 это вы , и поэтому будете двигаться, когда вы это делаете.

1 голос
/ 29 мая 2018

--soft: Говорит Git сбросить HEAD для другого коммита, поэтому индекс и рабочий каталог не будут изменены каким-либо образом. Все файлы, измененные между исходным HEAD и коммитом, будут размещены.

--mixed: так же, как и софт, это сбросит HEAD к другому коммиту. Он также сбросит индекс, чтобы он соответствовал ему, в то время как рабочий каталог не будет затронут. Все изменения останутся в рабочем каталоге и будут отображаться как измененные, но не промежуточные.

--hard: Это сбрасывает все - он сбрасывает HEAD обратно в другой коммит, сбрасывает индекс, чтобы соответствовать ему, и сбрасывает рабочий каталог, чтобы соответствовать ему.

Основное различие между --mixed и --soft заключается в том, изменен или нет ваш индекс. Узнайте больше об этом здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...