it-swarm.com.ru

В чем разница между git reset --mixed, --soft и --hard?

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

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

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

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

576
Michael Chinen

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


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

1187
mkarasek

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

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


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


Или для тех, кто использует программу с графическим интерфейсом, как «Башня» или «SourceTree»

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

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

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

63
timhc22

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

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

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

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

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

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

21
James Lawruk

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

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

 enter image description here

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

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

Основное различие между различными опциями команды git reset приведено ниже.

  • --soft: Сбрасывает только HEAD в выбранный вами коммит. Работает в основном так же, как git checkout, но не создает отдельное состояние головы.
  • --mixed (опция по умолчанию): сбрасывает заголовок в коммит, выбранный вами в истории, и отменяет изменения в индексе.
  • --hard: сбрасывает заголовок в коммит, выбранный вами в истории, отменяет изменения в индексе и отменяет изменения в вашем рабочем каталоге.
1
Vishwas Abhyankar

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

Я считаю, что это лучший способ думать о git reset. Вы не просто перемещаете HEAD ( все это делает ), вы также перемещаете ссылка на ветвь, например, master. Это похоже на то, что происходит, когда вы запускаете git commit (текущая ветвь перемещается вместе с HEAD), за исключением того, что вместо создания (и перехода к) фиксации new вы переходите к предыдущему совершить.

Это точка 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.

Измените свой индекс тоже

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 перемещают ветку, на которую ссылается HEAD.

Примечание о «такая-то команда перемещает ГОЛОВУ»:

Бесполезно говорить, что команда перемещает переменную HEAD. Любая команда, которая меняет ваше местоположение в истории коммитов, перемещает HEAD. Вот что такое HEAD, указатель на то, где вы находитесь. HEAD это вы , и поэтому будете двигаться, когда вы это делаете. 

1
De Novo

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

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

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

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

1
Nesha Zoric

Краткий ответ, в каком контексте используются 3 варианта:

To сохранить текущие изменения в коде но переписать историю коммитов:

  • soft: вы можете зафиксировать все сразу и создать новый коммит с новым описанием (если вы используете torotise git или любой другой графический интерфейс, это тот, который нужно использовать, так как вы можете пометить, какие файлы вы хотите в коммите и сделать несколько коммитов таким образом с разными файлами. В Sourcetree все файлы будут помещаться для коммита.)
  • mixed: Вам нужно будет снова добавить отдельные файлы в индекс, прежде чем делать коммиты (в Sourcetree все измененные файлы будут неизменными)

Чтобы фактически потерять ваши изменения также в коде:

  • hard: вы не просто переписываете историю, но и теряете все свои изменения вплоть до момента сброса
1
Nickpick

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

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

2.git добавить.

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

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

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

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

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

1
qinmu2127

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

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

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

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

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

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

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

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

1
Suresh Sharma

ответ mkarasek велик, простыми словами мы можем сказать ...

  • git reset --soft: установите HEAD для предполагаемого коммита, но сохраняйте свои изменения с момента последнего коммита
  • git reset --mixed: он такой же, как git reset --soft, но единственное отличие состоит в том, что он не вносит изменения с момента последнего коммита
  • git reset --hard: установите HEAD для указанного вами коммита и сбросьте все ваши изменения с последних коммитов, включая не зафиксированные изменения. 
0
Vivek Maru