git reset --hard 和 git reset --merge 之间有什么区别

发布于 2024-08-09 01:32:41 字数 1210 浏览 4 评论 0原文

在我的实验中,我无法发现

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 为空,就像第一次提交后一样。

有人可以想出说明差异的步骤吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

南街九尾狐 2024-08-16 01:32:41

来自 git Reset 手册页

--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 的更安全版本,当您的更改和其他人的更改混合在一起时,试图携带我们的更改。

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.

年华零落成诗 2024-08-16 01:32:41

文章“Git 撤消、重置或恢复?”总结了与 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答案,并由 博客文章,当您看到如下错误消息时,后者特别有用:

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

线程“[PATCH] 在合并期间拒绝合并" 也详细说明了这一点:

git reset --merge HEAD

它填补了相当不同的情况,即您与一些未提交的内容进行了干净的合并
工作树中发生更改,但随后希望再次放弃合并而不丢失未提交的更改。
如果没有更改,您只需使用 --hard,但在这里您想要在合并它们时移动分支尖端,类似于“git checkout -m” ' 是为了
移动HEAD

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.

眼中杀气 2024-08-16 01:32:41

tl;dr git reset --merge 是用于撤消合并的 git reset --keepgit reset --keepgit reset --hard 尝试保留未暂存的更改。此外, git reset --hard 可能会更改未暂存的文件(

任何未跟踪的文件或写入任何跟踪文件的目录都会被删除。

我认为您通常想了解的有关 git reset --merge 的内容已由 @manojlds 的 @manojlds(合并之前工作树中的更改;冲突或干净合并)。因为这看起来像 git reset --merge 的用例。

但您可能还需要考虑以下两种情况:

  1. 如果在合并之前工作树没有发生任何更改,并且您正在解决冲突,git reset --merge ORIG_HEAD< /code> 与 git reset --hard ORIG_HEAD 没有太大区别。除非您此时开始开发新功能(进行与解决冲突无关的更改)。也就是说,如果您想要撤消合并,您很可能想要撤消所有内容。在这种情况下,您只需执行 git merge --abort 即可。

    但在这种情况下, git reset --merge ORIG_HEAD 会保留未暂存的更改。对有冲突的文件进行的更改(丢弃)和对暂存文件进行的更改(中止)除外。

    尽管从理论上讲它可能很方便,但听起来不像 git reset --merge 的用例。


  2. 如果您没有在解决冲突,并且想要将 git reset --merge 到任意提交,它将尝试保留未暂存的更改。但 git reset --keep 也会如此。后者在合并过程中根本不起作用,并且会忽略分阶段的更改。

    如果无法保留未暂存的更改,它们将中止。如果您更改的文件在 HEAD 之间也发生过更改,就会发生这种情况。

tl;dr git reset --merge is git reset --keep for undoing a merge. git reset --keep is git reset --hard that tries to preserve unstaged changes. Also, git reset --hard may change unstaged files (git-reset):

Any untracked files or directories in the way of writing any tracked files are simply deleted.

I think what you generally want to know about git reset --merge is covered by by @manojlds (changes in the working tree before a merge; a conflict or a clean merge). Because that looks like the use case for git reset --merge.

But you may also want to consider the following 2 cases:

  1. If you had no changes in the working tree before a merge, and you're in the middle of resolving a conflict, git reset --merge ORIG_HEAD is not much different from git reset --hard ORIG_HEAD. Unless you start working on a new feature at this point (make changes unrelated to resolving a conflict). That is, if you want to undo the merge, you most likely want to undo everything. And in this case you can simply do git merge --abort.

    But git reset --merge ORIG_HEAD will preserve unstaged changes in this case. Except for changes made to files with conflicts (discard), and changes made to staged files (abort).

    Although theoretically it may be handy, it doesn't sound like a use case for git reset --merge.

  2. If you're not in the middle of resolving a conflict, and want to git reset --merge to an arbitrary commit, it will try to preserve unstaged changes. But so will git reset --keep. The latter simply doesn't work in the middle of a merge, and ignores staged changes.

    They will abort if they can't preserve unstaged changes. That will happen if you changed a file that was also changed between HEAD and <commit>.

半世蒼涼 2024-08-16 01:32:41

显然根据:

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

--hard - 将工作树和索引与要切换到的树相匹配。对工作树中跟踪文件的任何更改
因为 丢失了。

--merge - 重置索引以匹配指定提交记录的树,并更新指定提交之间不同的文件
提交和工作树中的当前提交。

Apparently according to:

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

--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.

挖个坑埋了你 2024-08-16 01:32:41

当您对工作树中的更改进行拉取并发现合并未按预期进行时(您可能期望提交不会影响您正在处理的文件),这会很有帮助。此时,如果您执行 git reset --hard ORIG_HEAD ,则会清除所有内容,包括本地更改。如果您执行git reset --merge ORIG_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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文