В чем разница между git reset --hard и git reset --merge - PullRequest
38 голосов
/ 28 октября 2009

В моих экспериментах я не смог найти никакой функциональной разницы между

git reset --hard

и

git reset --merge

Инструкции по использованию также не дают подсказок

--hard                reset HEAD, index and working tree
--merge               reset HEAD, index and working tree

Я регулярно использую опцию --hard, чтобы понять, как это работает. В чем разница между параметрами --merge и --hard?

Ура, Olly

Возможно, здесь поможет пример, давайте используем следующую последовательность:

cd git_repo
touch file_one
git add file_one
git commit -m "commit one" # sha1 of 123abc
echo "one" >> ./file_one
git commit -a -m "commit two" # sha1 of 234bcd
echo "two" >> ./file_one
git add . # populate index with a change
echo "three" >> ./file_one # populate working area with a change

Теперь, если я попытаюсь

git reset --merge 123abc

Я получаю

error: Entry 'file_one' not uptodate. Cannot merge.
fatal: Could not reset index file to revision '123abc'

причина в том, что file_one имеет изменения как в рабочей области, так и в индексе

Чтобы исправить это, я делаю

git add .
git reset --merge 123abc

На этот раз это работает, однако я получаю тот же результат, что и git reset --hard. Индекс пуст, рабочая область пуста, file_one пуст, как это было после первой фиксации.

Может кто-нибудь придумать шаги, иллюстрирующие разницу?

Ответы [ 4 ]

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

С git reset manpage :

--hard    Matches the working tree and index to that of the tree being
               switched  to. Any changes to tracked files in the working tree since
               <commit> are lost.

--merge
              Resets the index to match the tree recorded by the named commit, and
              updates the files that are different between the named commit and
              the current commit in the working tree.

Предполагается, что git reset --merge является более безопасной версией git reset --hard, когда ваши изменения и чьи-то другие изменения смешиваются вместе, пытаясь нести наши изменения.

12 голосов
/ 25 сентября 2012

В статье " Git undo, reset или revert? " кратко описаны различные варианты использования при ORIG_HEAD:

# Reset the latest successful pull or merge
$ git reset --hard ORIG_HEAD

# Reset the latest pull or merge, into a dirty working tree
$ git reset --merge ORIG_HEAD

Как отмечено manojlds ' answer и проиллюстрировано в блоге , последнее особенно полезно, когда вы видите сообщение об ошибке, подобное:

fatal: You have not concluded your merge. (`MERGE_HEAD` exists)

Поток " [PATCH] отказывается от слияния во время слияния ", также подробно указывает этот пункт:

git reset --merge HEAD

Это заполняет совсем другой случай, когда вы сделали чистое слияние с некоторыми незафиксированными изменения в рабочем дереве, но затем необходимо снова отменить слияние, не теряя незафиксированные изменения.
В отсутствие изменений вы просто использовали бы --hard, но здесь вы хотите переместить подсказку ветвления при объединении их, подобно тому, что 'git checkout -m' делает для Перемещение HEAD.

8 голосов
/ 13 августа 2012

Это полезно, когда вы выполняете извлечение с изменениями в рабочем дереве и обнаруживаете, что слияние не соответствует ожидаемому (возможно, вы ожидали, что коммиты не повлияют на файлы, с которыми вы работали). На этом этапе, если вы делаете git reset --hard ORIG_HEAD, вы сдуваете все, включая ваши локальные изменения. Если вы сделаете git reset --merge ORIG_HEAD, вы сохраните свои локальные изменения.

3 голосов
/ 28 октября 2009

По-видимому, согласно:

http://www.kernel.org/pub/software/scm/git/docs/git-reset.html

- hard - Соответствует рабочему дереву и индексируется дереву, на которое переключается. Любые изменения в отслеживаемых файлах в рабочем дереве поскольку <commit> потеряны.

- объединить - Сбрасывает индекс в соответствии с деревом, записанным именованным коммитом, и обновляет файлы, которые отличаются между именованным commit и текущий коммит в рабочем дереве.

...