Git reset soft vs mixed - 为什么要使用--mixed?

Git reset soft vs mixed - why use --mixed at all?

当使用 git reset 时,如果第一个选项意味着重新添加 --soft 已经处理的文件,为什么人们更愿意使用 git reset --mixed 而不是 git reset --soft

此外,关于这两个选项之间的区别 - 如果我 不是 使用 git reset --soft(例如作为练习),是否存在 git reset --mixed && git add 将无法模仿 git reset --soft 行为 ?


编辑:我知道有类似的问题,但他们没有深入研究 git reset --mixedgit add 可能不等同于 git reset --soft 的边缘情况,他们主要总结了已知的文档。

你说得对,你经常可以用 git reset --mixedgit add 模仿 git reset --soft

但是,我可以想象不可能的边缘情况。假设您编辑了一个文件,然后使用 git add 将您的更改添加到索引中,但之后您意识到这是错误的,并且您使用某些编辑器返回到以前的版本。现在,您认为文件根本没有更改,但您的更改仍在索引中。不同之处在于:git reset --soft 将保留您的分阶段更改,而使用 git reset --mixed 它们将永远丢失(git add 不会帮助您,因为您没有什么可添加的)。

这些标志有不同的用例:--mixed 通常用于删除索引中意外添加的更改,我感觉 --soft 很少使用.我只使用过一次 --soft 标志,当时我忘记创建功能分支并在 master 上提交。

考虑一下 git reset(在其三种模式中,软、混合、硬,而不是其他根本不是这三种模式之一的其他东西)的作用。你运行:

git reset --<mode> <commit-specifier>

它会做以下三件事,或者可能是 2 件,或者 1 件:

  1. (--soft, --mixed, --hard) 它更改 当前分支名称 ,如存储在 HEAD,指向给定的提交。使用 --soft,它现在停止了。

  2. (--mixed and --hard) 它用 commit 的内容替换现有的索引内容 select 在步骤 1 中编辑。使用 --mixed(或默认值),它现在停止。

  3. (仅限 --hard)它用步骤 2 中更新的文件替换工作树内容。

现在,您可以,如果您选择,select 当前提交 作为第 1 步中的目标,通过例如 运行ning git reset HEAD。如果这样做,步骤 1 中更新的当前提交就是当前提交。也就是说,第 1 步没有实际更改。

如果你运行 git reset --soft HEAD,第1步没有改变,然后git reset退出。所以这绝对没有任何作用。

如果你 运行 git reset 没有 --soft,然而——根本没有参数,默认为 --mixed,或者有 --hard——它继续第 2 步:将索引的内容替换为一直冻结到当前提交中的文件。实际上,这会取消您之前所做的任何 git add

如果您的目标是之后再重新做所有 git add,这没有用。但是,如果您的目标是 而不是 重做所有这些 git add,则可以。例如,考虑这个例子——它本身并不是很有用,但只是为了说明:

git checkout somebranch
<edit for a while, test, `git add .`>

# think: wait, I don't want to commit everything
git reset      # index now matches HEAD

<edit README file to announce that the NEXT commit changes a lot of things>
git add README
git commit     # make a commit in which everything is the same except README

git add .
git commit     # make final commit in which everything is changed

为了理解所有这些,请记住每个文件始终有 三个 个副本:

  • 每个文件(README.mdmain.py 等,无论你有什么文件)都有一个只读的、永远冻结的副本当前提交。您可以随时使用 git checkoutgit reset 更改哪个提交是 当前提交 ,但提交本身一直被冻结:none 它的文件永远不会改变,它的提交消息、作者等也不会改变。

  • Git 的索引中有一份冻结的格式文件副本。1 你可以随心所欲地改变它:你可以用另一个文件的副本或同一文件的另一个版本覆盖文件的副本。您甚至可以使用 git rm从索引中完全删除 文件。索引副本是冻结格式,准备提交,但它本身不是提交,所以它可以被更改。

  • 最后,有一个可用版本的文件。它不是某种特殊的 Git-only 格式,您的计算机程序的 rest 实际上可以 使用 这个版本的文件。该版本位于您的 work-tree.

文件的索引副本与至少一个其他副本(HEAD 副本、工作树副本或两者)匹配是非常典型的,但实际上,您可以拥有所有三个文件与众不同。为此,只需:

  • 编辑工作树副本(一定要保存它以便 git add 可以看到它);
  • 使用git add将工作树副本复制到索引;和
  • 编辑工作树副本(并确保再次保存)。

现在文件已暂存提交,这意味着 HEAD 和索引副本不同,未暂存提交[=109] =],这意味着索引和工作树副本不同。


1从技术上讲,索引中的内容只是模式、文件名和 对内部 Git 的引用 blob 对象。 blob 对象表示文件内容 的冻结格式副本。 Reset (git reset) 将模式、名称和哈希 ID 复制到索引中。添加 (git add) 通过创建新的 blob 对象或查找已经存在的 blob 对象来压缩(准备好冻结)工作树文件,稍后将重新扩展到工作树文件.