提交未暂存的文件

5

我是Git的新手,正在使用Git扩展。我想问一下,当我提交目录时,这些文件是否会自动进入暂存区或者说它们会在没有进入暂存区的情况下被提交?

我能否在不暂存的情况下提交文件?


为什么你想这样做?git add -u 可以在一个命令中为你暂存所有内容。 - Nix
可能是Git commit -a "untracked files"?的重复问题。 - Nix
你可以轻松地使用@David_Tryon的答案来为某些东西设置别名,以实现你想要的功能。 - Nix
是的,类似于 git config --global alias.yabadabadoo !git add -u && git commit -a 这样的东西。 - Andrejs Cainikovs
在我看来,那是一个非常糟糕的做法。 - Sébastien Dawans
显示剩余2条评论
3个回答

15
这里值得一提,所有这些方法都使用了一个索引,也称为暂存区或缓存区。
当Git进行新提交时,它使用“索引”中的内容。正如短语“索引”所示,有一个单独且特殊的突出事物:索引,而不是索引之一。但实际上,Git可以使用一些其他的索引。我们需要知道“索引”是什么以及成为“索引”的意义,与一些其他索引相比。
简单来说,索引是Git用来构建下一个提交的东西。我们从当前或HEAD提交开始。您运行git checkout master或git checkout branch等命令,Git会在您的工作树中填充一堆文件。它还将相同的文件放入(单个、特殊、突出)索引中,也称为暂存区。这意味着索引/暂存区最初充满许多文件:大多数是您在工作树中做工作的相同文件。例外情况是一些工作树文件可能是未跟踪的。
未跟踪的文件是不在索引中的文件。真的很简单:任何不在索引中的文件都未跟踪;任何在索引中的文件都已被跟踪。索引中的文件最初与通过git checkout检出的文件相同,这些文件已放入您的工作树中。
然后,您对一堆文件进行了大量更改。但是,如果您现在运行git commit,则索引/暂存区仍具有原始的git checkout版本,而不是修改后的工作树版本。因此,您必须将更改的文件复制到索引中以便于git提交。
这有点麻烦,因此Git有git add -u和git commit -a命令。但是,这两者都只查看当前索引中的内容,并将那些新的工作树版本复制到索引中。所以git commit -a -m "commit message"不会添加工作树中存在但不在索引中的文件-即当前未跟踪的文件。这与git add -u相同:只有已跟踪的文件才会更新。
以下是有点复杂的地方:
除上述之外,git commit可以采用路径名作为参数:
git commit -m "some message" file1 file2

例如。但这意味着需要使用--only标志,也就是仅提交file1file2中的更改。您还可以运行以下命令:

git commit -m "some message" --include file1 file2

这将覆盖--only的设置。

工作原理是Git可以使用一个不同的索引,而不是标准索引。使用--only时,Git会从HEAD提交构建一个新的临时索引。然后,Git将指定的文件从工作目录复制到这个临时索引中,替换旧版本或添加新文件。然后,Git从此临时索引中创建一个提交:新提交与HEAD提交具有完全相同的所有文件,除了由于--only file1 file2添加的任何内容。

如果您使用--include,则Git通过复制当前索引而不是再次提取HEAD来创建其临时索引。因此,您到目前为止已经用git add添加的内容也在临时索引中。然后,Git添加指定的文件,并进行新的提交。

在所有情况下,在Git进行新提交之后,它必须修复真实的索引,因为现在您已经提交了最新的file1file2(如果您使用了--include,则可能还有其他更新)。如果使用了--include,则临时索引变为真实索引。

如果您使用了--only,这是最复杂的情况。在此时,Git也会将添加的文件复制到真实索引中,但除此之外将不会更改真实索引。这样,您之前暂存的内容仍然保留。新提交中包含了HEAD提交中的所有内容(通过临时索引),除了指定的文件(已添加到临时索引中)。而现在,您刚刚明确提交的任何内容也会像运行git add那样,被git add真实索引中。


1
哇,非常全面。谢谢! - pfabri
这是一个很棒的解释。有趣的是,如果能以某种方式看到临时索引以验证工作的细微差别会更好。 - theOne
@theOne:临时索引仅在一个git commit命令的持续时间存在。你可以从某些方面看到它:例如,您的预提交钩子是使用环境变量GIT_INDEX_FILE运行的,该变量设置为显示临时文件的名称(默认设置未设置或设置为标准索引)。不幸的是,没有完美且简单的方法来测试这一点,因为git worktree add会添加一个工作树,其标准索引不是.git/index而是.git/worktrees/<id>/index,其中<id>是某个ID,而且不能保证将来不会更改。 - torek
1
同时,如果您使用运行编辑器的git commit命令,并在该编辑器等待您(人类)编辑提交消息时使用第二个窗口或类似工具来查看.git目录内部,您可以找到临时索引。对于git commit --only,实际上有三个活动索引文件;对于git commit --include,则有两个。但是再次强调,这些都是没有真正承诺的实现细节。这有点不幸,因为它限制了您在预提交挂钩中所能做的事情。 - torek
+1 简直太棒了!现在我使用 git commit -m "一些信息" file1 来提交对 file1 的轻微更改(例如修复空格),这些更改与当前工作无关,而且不会干扰我暂存区的内容。(在阅读这个答案之前,我会取消暂存所有文件,暂存更改后的 file1,然后提交,最后再重新暂存以前的文件以继续...那非常繁琐...git commit --only 真是太棒了)。 - Eric Mutta
1
@EricMutta:你甚至可以将 --amend 与此结合使用,通过使新提交的父项成为被剔除提交的父项来将先前尖端提交从分支中移除,从而修复上一个提交中的故障。但我通常发现过于花哨是有害的,最好只是进行一堆较小的提交,并使用 git rebase -i 来组合和修复事情。 - torek

13

是的,你可以使用am来暂存和提交代码:

git commit -am "我的提交信息"

然而,我通常使用git add -u,因为上述命令不会暂存未跟踪的文件。


只有被跟踪的文件才会被处理...? - Nix
我的未跟踪文件是出于选择而未被跟踪的。不要将Git误用为垃圾容器。 - vonbrand

0

不需要暂存文件就提交

git commit -a(这里的-a将跳过暂存部分,但如果文件是新的且未被跟踪,则需要运行git add file_name.ext)


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