What's the difference between git reset
In my experiments I haven't been able to find any functional difference between
git reset --hard
and
git reset --merge
The usage instructions don't give any hint either
--hard reset HEAD, index and working tree
--merge reset HEAD, index and working tree
I regularly use the --hard
option so understand how that works. What's the difference between the --merge
and the --hard
options?
Cheers, Olly
Perhaps an example would help here, let's use the following sequence:
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
Now if I try
git reset --merge 123abc
I get
error: Entry 'file_one' not uptodate. Cannot merge.
fatal: Could not reset index file to revision '123abc'
the reason being that file_one has changes in both the working area and the index
To remedy this I do
git add .
git reset --merge 123abc
This time it works, however, I get the same result as git reset --hard
. The index is empty, working area is empty, file_one is empty, as it was after first commit.
Can someone come up with the steps that illustrate the difference?
From 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.
The git reset --merge
is meant to be a safer version of git reset --hard
, when your changes and somebody else changes are mixed together, trying to carry our changes around.
The article "Git undo, reset or revert?" summarizes the different usages, when used with 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
As mentioned by manojlds's answer, and illustrated by the blog post, the latter is especially useful when you see an error message like:
fatal: You have not concluded your merge. (`MERGE_HEAD` exists)
The thread "[PATCH] refuse to merge during a merge" also details that point:
git reset --merge HEAD
It fills the rather different case where you did a clean merge with some uncommitted changes in the worktree, but then want to discard the merge again without losing the uncommitted changes.
In absence of the changes, you would just use --hard
, but here you want to move the branch tip while merging them over, similar to what ' git checkout -m
' does for moving HEAD
.
This is helpful when you do a pull with changes in working tree, and find that the merge is not as expected ( you might have been expecting that the commits would not affect the files you were working on ). At this point, if you do git reset --hard ORIG_HEAD
, you blow away everything, including your local changes. If you do git reset --merge ORIG_HEAD
, you will keep your local changes.
上一篇: 撤消git重置?
下一篇: git reset有什么区别?