git reset --merge和git reset --keep的区别

21

我已经阅读了文档,但是我很难理解它们之间的区别。

git reset --merge

而且

git reset --keep
请提供简单的解释和/或示例。

3
在我看来,它们并不完全相同。一个问题是询问它们的功能,而另一个问题则是询问为什么要使用它们。 - Steve Bennett
@SteveBennett 我认为它们足够接近,可以作为重复关闭,但请随意投票以重新打开。 - jub0bs
2个回答

18

我同意文档不是很清晰。通过测试,我发现了三个关于文件操作的差异:

  • 存在暂存更改
  • 没有未暂存更改

总结:

  • reset --merge 总是放弃索引(暂存更改);如果任何文件上存在未暂存和已暂存的更改,则中止操作。
  • reset --keep 保留索引,但取消暂存;如果重置目标触及相同的文件,则中止操作。

测试场景:

echo First > file.txt
git add file.txt
git commit -m 'first'
git tag v1
echo Second >> file.txt
git commit -am 'second'
git tag v2
echo New > newfile.txt
git add newfile.txt
git commit -m 'third'
git tag v3
echo 'More stuff' >> file.txt
git add file.txt

现在我们有三个提交,'file.txt' 在v1和v2之间发生了变化,但在v2和v3之间没有发生变化。

索引和新HEAD之间没有变化

在这种情况下:

  • git reset --merge v2会丢弃那些更改
  • git reset --keep v2会保留它们,但取消暂存它们。

索引和新HEAD之间有变化

如果我们尝试重置为v1:

  • git reset --merge v1会丢弃更改
  • git reset --keep v1则会拒绝:

    error: Entry 'file.txt' would be overwritten by merge. Cannot merge.
    fatal: Could not reset index file to revision 'v1'.
    

index和新HEAD之间的更改以及未提交的更改

    git echo "Even more things" >> file.txt

现在两者都失败了,但出现的错误信息略有不同:

  • git reset --merge v1

  • error: Entry 'file.txt' not uptodate. Cannot merge.
    fatal: Could not reset index file to revision 'v1'.
    
  • git reset --keep v1

    将当前HEAD指针重置为版本v1,保留当前工作目录和暂存区的更改。
  • error: Entry 'file.txt' would be overwritten by merge. Cannot merge.
    fatal: Could not reset index file to revision 'v1'.
    

关于一个无关文件的暂存和非暂存更改

echo Unrelated > unrelated.txt
git add unrelated.txt
echo Stuff >> unrelated.txt

现在有些奇怪:

  • git reset --merge v1

error: Entry 'unrelated.txt' not uptodate. Cannot merge.
fatal: Could not reset index file to revision 'v1'.
  • git reset --keep v1

    保留两组更改,但未暂存。

  • 没有暂存的更改,但有未暂存的更改

    为了完整起见,这两种情况表现相同:重置成功,文件保持未暂存状态。


    这是一个非常好的答案,不仅因为它很详细,而且测试场景可以复制粘贴,所以你可以自己看到。 - mellow-yellow

    7

    在处理合并冲突时,它们是不同的,例如这将生成一个冲突。

    git init
    echo 333 > foo.txt
    git add foo.txt
    git commit -m 333
    git checkout -b feature
    echo 444 > foo.txt
    git commit -am 444
    git checkout master
    echo 555 > foo.txt
    git commit -am 555
    git merge feature
    

    那么

    $ git reset --keep
    fatal: Cannot do a keep reset in the middle of a merge.
    
    $ cat foo.txt
    <<<<<<< HEAD
    555
    =======
    444
    >>>>>>> feature
    

    对比

    $ git reset --merge
    
    $ cat foo.txt
    555
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接