繁体   English   中英

git commit 和 git commit 有什么区别<file>和 git commit --only?

[英]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 中得到修复。 特别可怕的是,它只是默默地忽略新文件! 您可以获得不包含您命名的文件的提交。 这似乎不仅是一个错误,而且是一个糟糕的错误。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM