如何在不暂存文件的情况下将新文件添加到Git?

58
为了有效地使用 git(如其原意),我会进行小的原子提交,尽管我也有更长的工作时间,在这些时间中需要修改不止一件事情。因此,我经常使用 git add -p 命令。然而,对于全新的文件,这个命令并不适用,因为我往往会忘记它们。
我想要做的是告诉 git 存在一个新文件需要跟踪,但并不需要将其加入暂存区:
例如,运行 git status 的结果如下:
# On branch my-current-branch
# Your branch is ahead of 'origin/my-current-branch' by 2 commits.
#
# Changes to be committed:
#
<<STAGED SECTION>> // A
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
<<UNSTAGED-YET-KNOWN SECTION>> // B
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
<<UNKNOWN SECTION>> // C
如果我在C部分有一个文件foo,并使用git add foo命令,它将进入A部分。如果我使用git add -N foo命令,它会同时进入A和B两个部分。但是,这意味着它将被包括在下一次提交中,至少作为有一个新文件的事实。
我希望它只能进入B部分,这样我可以稍后使用git add -pgit add foo(或其他命令)将其添加到A部分。
编辑
关于add -N解决方案,这不起作用,因为如果我在说了add -N但没有正确添加它之后尝试提交,git会抱怨,因为它不知道如何处理空文件:
foo: not added yet
error: Error building trees

我建议你使用-N选项,但是你在帖子中已经提到它对你无效了!那么我的建议是通过及时更新.gitignore文件来保持未跟踪文件部分为空,这样任何新的文件都会立即显现出来。 - Robert
@Robert:是的,我实际上有一堆gitignores,但我无法完全保持该部分干净,总会有一些垃圾,而我的眼睛似乎已经习惯了不看到那个部分。 - bitmask
我认为git没有一个可以完全满足你要求的选项... -N选项似乎最接近,但如果你不想暂存创建(这应该是无害的),我看不到其他选择,除非使用未跟踪的文件来实现此目的。在我看来,保持该部分干净是一个好的做法 - 所有东西都是源文件或构建产品。 - Robert
1
我想建议使用 git add foo + git reset HEAD foo,但事实证明 reset 命令会将新文件移回到 C 区而不是旧文件的 B 区。真气人... - Andras Nemeth
注意:Git 2.5(2015年第二季度)现在使“git add -N”成为可行的解决方案:请参见[下面的我的回答](https://dev59.com/EWgu5IYBdhLWcg3wxZzd#30341980) - VonC
3个回答

45

使用Git 2.5,git add -N/--intent-to-add是正确的解决方案。
新文件不会成为下一次提交的一部分。

请参见Nguyễn Thái Ngọc Duy(pclouds)的提交d95d728(合并到d0c692263):

diff-lib.c:调整diff中i-t-a条目的位置

问题:

通过"git add -N"添加的条目是提醒用户不要忘记在提交之前添加它们的条目。即使它们不是真实的,这些条目也会出现在索引中。它们在索引中的存在导致像这样令人困惑的"git status":

On branch master
Changes to be committed:
        new file:   foo

Changes not staged for commit:
        modified:   foo

如果你执行了"git commit","foo"将不会被包含,即使"status"报告它为"to be committed"。

解决方案:

这个补丁改变了输出结果,变成了:
On branch master
Changes not staged for commit:
        new file:   foo

no changes added to commit

那就是说:
将这些路径视为“尚未添加到索引中,但Git已经知道它们的存在”; “git diff HEAD”和“git diff --cached HEAD”不应该涉及它们,而“git diff”应该显示它们作为新增文件。

3
也许你可以尝试编写一些预提交挂钩,以便在有未跟踪的文件时提醒你。但这需要你始终保持git目录的清洁工作,同时(显然)你需要保持最新的.gitignore文件。
另外,还可以尝试使用git add -i命令,它类似于git add -p,但也具有添加新文件的界面。

git add -p 意味着 git add -i,但直接跳过到选项 5: patch。只要每次执行 5: patch 时检查选项 4: add untrackedgit add -i 就能帮助你完成所有操作。 - Christopher

1
你可以在进行更改之前提交一个空文件到该路径。如果你已经在那里写了东西,将文件移开,创建一个空文件,提交它,然后像平常一样添加 -p 并使用 git commit --amend 命令,这样你就不会有一个“添加空文件”的提交记录了。

3
我认为如果我使用 add -N 命令,它会自动被提交为空。然而,使用 --amend 的解决方案意味着我必须记住这样做。虽然这不像完全忘记一个文件那么糟糕,但这意味着要更改先前的提交记录,而我想避免这种情况。至少这是一个折中办法,而不是一种干净利落的解决方案。 - bitmask
1
我不认为这是黑客行为。使用修改/变基来清理未发布的历史记录没有任何问题。 - Daenyth
1
你也可以给一些东西起别名,比如“git add-empty”之类的,这样就有了可重复的过程,但你不必记住它。 - msouth

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