[英]what"s the difference between git commit <file> and git commit --only?
有三种使用git commit
(无论如何都没有--amend
):
git commit
,不命名任何文件:这意味着提交当前索引。
git commit --only file1 ... fileN
,您可以在其中命名一些文件并使用--only
选项。 稍后我们将对此进行描述。
git commit --include file1 ... fileN
,您可以在其中命名一些文件并使用--include
选项。 我们稍后也将对此进行描述。
如果您选择列出一些非零数量的文件,但省略--only
选项,Git将采用--only
选项。 如果你不希望--only
选项,则必须指定--include
选项。 如果你选择在命令行中列出一些文件,你必须选择这两个选项之一,如果你选择失败,Git 会为你选择。 所以--only
仅仅是相反--include
。
要正确理解所有三种操作模式,您需要了解 Git 从索引构建提交。 通常它使用索引。 这是上面列出的第一个模式: git commit
,没有任何文件名,现在使用索引中的任何内容。
索引本身是一种有点隐藏的数据结构。 它有三个名称,要么反映了它的重要性,要么反映了相当糟糕的初始名称,即“索引”。 第二个名字是临时区域,因为该指数的作用是充当可以在其中构建,或阶段性-the下次提交你会做的地方。 这个东西的第三个名字——这个索引或暂存区——是缓存。
索引开始时保存当前提交中所有文件的副本,这些副本是在您运行git checkout branch
时提取的。 这些文件从分支提示提交复制到索引/暂存区,也复制到工作树中,您可以在其中处理它们。 名称索引来自于索引跟踪工作树的事实:它索引它。 (请参阅此处的动词定义。)
当你运行git commit
在正常模式下,Git的封装了所有在索引中右边的文件,然后,一切都在提交签出,与文件,您的文件git add
-ed覆盖从工作文件-树。 这些文件成为新的快照。 Git 会写出快照本身、您作为提交作者的姓名和电子邮件地址,以及您的其他元数据,例如您的日志消息。 它将新提交的父级设置为分支的前一个提示,然后将新提交的哈希 ID 写入当前分支名称,这样新提交现在就是当前提交。
由于 Git 刚刚从索引构建了新的提交,新的、当前的提交和索引匹配。 因此,通过修改工作树文件并将它们复制到索引中,一切都为您可能进行的下一次提交做好了准备。
--only
和--include
工作要使用--include
构建新提交,Git 本质上只是将文件添加到索引并提交。 1这非常简单:看起来好像您运行了git add file1 ... fileN
然后运行了git commit
。 新提交是从这个修改后的索引构建的,现在是索引,因为它现在匹配新的当前提交。
然而,对于--only
,Git 有问题。 该指数常规one-也很可能被修改,可能不再匹配当前提交。 因此,实际上 Git 所做的是将当前提交提取到临时索引中,使用git add
将工作树文件复制到该临时索引中,然后从临时索引构建提交。 这部分并不复杂:新提交被从索引建成,它只是没有索引。 但是一旦完成,Git 又回到了问题上:真正的索引——你可能修改过的索引——与 Git 刚刚做出的新提交不匹配,并且可能与之前的提交不匹配。 它不匹配任何东西,这是一个大混乱。
在成功提交之后,此时 Git 所做的是将那些相同的文件复制到实际索引,以便索引中的file1 ... fileN
更新以匹配您刚刚提交的内容。 同时,实际索引中的所有剩余文件仍然存在,但是它们在您运行git commit --only
之前看起来是git commit --only
。
请注意,您在实际索引中仔细暂存的文件(例如,使用git add --patch
既不匹配工作树也不匹配旧的(不再是当前的)提交可能仍然是您暂存它们的方式。 但是,如果您将其中一个文件命名为--only
文件之一,那么精心设计的版本现在就消失了! 由于提交后git add
它已被替换为工作树版本。 2
1 在内部,它更复杂:Git 仍然构建一个临时索引,就像它为--only
所做的--only
。 但是,如果提交成功,临时索引将成为常规索引。 所以这比--only
。 请注意,这个“本质上”的短语掩盖了许多错误:例如,如果文件对git
是全新的,那么--include
部分至少在某些版本的 Git 中会失败,而直接git add
会起作用。
我在这里至少说一些,因为我刚刚在 Git 2.24.0 中测试了它,这是非常最新的,这可能意味着它在所有版本中都失败了; 但这似乎是一个错误,因此它可能会在未来版本的 Git 中得到修复。 特别可怕的是,它只是默默地忽略新文件! 您可以获得不包含您命名的文件的提交。 这似乎不仅是一个错误,而且是一个糟糕的错误。
2与git commit --include
,这有一些粗糙的边缘,尤其是在当前不在索引中的文件的情况下。 但是,至少在 Git 2.24 中的行为稍微好一些,因为 Git 会在此处生成错误消息,而不是默默地忽略该文件。
答案在您列出的文档片段中:
--only
通过获取命令行上指定路径的更新工作树内容进行提交,忽略已为其他路径暂存的任何内容。 如果命令行上给出了任何路径,则这是
git commit
的默认操作模式,在这种情况下,可以省略此选项。
当您在命令行中添加文件路径时, --only
不会向命令添加任何内容,并且您在问题中描述的第二个选项所描述的语义适用。
另一方面,正如--only
的其余描述所解释的那样,如果它与--allow-empty
--amend
一起使用,则索引的内容(暂存文件)将被忽略。
git commit --amend
通过添加当前暂存文件并更改其提交消息git commit --amend
修改当前提交。 使用--only
,不会修改提交的内容(忽略暂存文件),只会更新提交消息。
我不清楚--only
如何改变git commit --allow-empty
的行为。
但是,-- --allow-empty
在 Git 的日常工作中没有任何用处。 添加它是为了帮助将其他 VCS-es 的存储库自动转换为 Git。 Fe 当一个分支被创建时,Subversion 会创建一个从 Git 的角度来看是空的新提交。 --allow-empty
允许git-svn
在将 Subversion 存储库转换为 Git 时创建这样的空提交。
git commit -- 从给定文件中获取提交消息。 在参数中,您应该输入您想要从存储库中获取的文件的名称。
git commit --only 是 git commit 的默认操作模式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.