想象一下,您已经暂存并提交了许多更改,但随后决定将这些更改分成两个提交。对于新创建的文件,您可以分阶段从提交中删除它们,而无需将它们从磁盘中删除(使用git rm --cached filename
)。修改后的文件是否有类似的命令?
从本质上讲,我希望能够暂存上一次提交的文件版本,然后能够重新运行git add -p filename
以选择哪些更改属于第一次新提交与第二次提交。我不希望磁盘上的任何内容发生变化;我的唯一目标是用最少的工作将一个提交分成两个。
git checkout HEAD~1 -- filename
暂存我想要的,但从磁盘中删除更改。我需要它们保留在磁盘上,以便我可以继续将它们添加到下一次提交中。(注意:您可以使用git reset filename && git checkout filename
撤消此命令)
git add HEAD~1 -- filename
感觉它应该做我想做的,但该命令无法运行fatal: pathspec 'HEAD~1' did not match any files
正如博士所指出的,git reset
可以做到这一点,因为git reset
的许多潜在工作之一是在不接触工作树的情况下将文件从提交复制到索引。
这有点令人惊讶,因为git reset
的默认作业首先将当前分支(如HEAD
所示)移动到一些新的用户指定的提交,然后才可能 - 取决于--soft
vs--mixed
vs--hard
- 也将文件从用户指定的提交复制到索引,然后可能复制到工作树。但是,当git reset
与路径名一起使用时,它会改变策略,完全放弃移动当前分支作业。 这就是为什么git reset
不允许--hard
、--soft
或--mixed
路径名的原因。
当git reset
移动当前分支时,如果您(用户)未指定某些特定提交,则git reset
选择的提交是当前分支命名的提交。 因此,从提交$old
到提交$new
的这种"移动"是$old
$new
,并且根本没有运动。 这就是为什么没有参数的git reset --soft
是无操作,以及为什么没有额外参数的git reset --mixed
或git reset --hard
不会更改当前提交,但会重置索引,也许还有工作树。
最终,我始终认为git reset
将太多操作打包到一个面向用户的命令中:它应该至少是两个,甚至可能更多,单独的面向用户的命令,所有这些命令都可以git reset
作为我们如何完成这种面向用户目标的操作的管道版本运行。git checkout
命令也会这样做,因为它有几个不同的用户目标(切换到新分支,从一个特定提交获取一个特定文件而不切换分支,等等)。