在git add -h
我可以看到以下选项:
-N, --intent-to-add record only the fact that the path will be added later
但我不明白何时应该使用此选项。这个选项真正做了什么,以及如何使用它?
Blue112's answer部分正确。 git add --intent-to-add
确实为工作副本中每个指定的未跟踪文件的临时区域/索引添加了一个空文件,但其中一个主要目的是使您能够将git diff
与尚未添加到Git存储库的文件一起使用然而,通过将未跟踪文件与临时区域中的空版本区分开来:
$ echo foo > foo.txt
$ git diff foo.txt
$ git add --intent-to-add foo.txt
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: foo.txt
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)
modified: foo.txt
$ git diff --staged foo.txt
diff --git a/foo.txt b/foo.txt
new file mode 100644
index 0000000..e69de29
$ git diff foo.txt
diff --git a/foo.txt b/foo.txt
index e69de29..257cc56 100644
--- a/foo.txt
+++ b/foo.txt
@@ -0,0 +1 @@
+foo
一旦你对文件进行了差异化,你可以通过简单地执行一个正常的git add
将非空版本添加到临时区域/索引:
$ git add foo.txt
git commit -a
同样,由于--intent-to-add
通过将这些文件的空版本添加到临时区域/索引来使未跟踪的文件“已知”给Git,它还允许您使用git commit --all
或git commit -a
将这些文件与您已知的已修改文件一起提交,这是否则你将无法做到。
如official Linux Kernel documentation for git commit
所述:
使用
-a
[或--all
]开关和commit命令[将]自动“添加”来自所有已知文件的更改(即已在索引中列出的所有文件)...然后执行实际提交
来自official Linux Kernel git add
documentation:
-N --intent-to-add
仅记录稍后将添加路径的事实。路径的条目放在索引中,没有内容。除了其他方面,这对于使用
git diff
显示此类文件的未分级内容并使用git commit -a
提交它们非常有用。
user456814's answer很好地解释了git add -N
的用途。我只想更详细地解释背景中发生的事情。
您可以将git视为维护文件更改的历史记录,例如创建,修改和删除(让我们称之为增量)。在最近的提交之前,增量是非常自我解释的,但是当你在项目中工作以准备一个新的提交时,事情变得更加复杂。在这种情况下,有三种不同类型的增量。
(旁注:大多数人,当第一次介绍给git时,会被教导类似于“在git中进行需要两个步骤;首先你做git add
然后你可以做git commit
”。虽然这是真的,但它只会引起人们对是承诺的delta类型。了解git add -N
也需要了解其他类型的增量。)
通常称为“分阶段更改”,当您运行git status
时,这些增量会出现在顶部,如果有的话。如果你的shell支持颜色,它们将是绿色的。
当你git add
文件时,它会被提升到这个类别。如果您运行没有任何标志的git commit
,这些更改将实际包含在内。
当你运行git status
时,这些增量出现在第二位,如果有的话。如果你的shell支持颜色,它们将是红色的。
这些是您对git存储库中尚未提交且尚未移至#1的文件所做的更改。编辑文件然后保存时,默认情况下它将显示在此类别中。
对于要在此类别中显示的文件,必须在最近的提交中存在EITHER,或者如果要提交#1中的更改,则添加该文件。否则,它将出现在类别#3中。
(注意:因为您选择何时将文件“提升”到类别#1中,所以可以在#1和#2中显示相同的文件。例如,我可以看到
modified: abc.txt
#1中的绿色,和
modified: abc.txt
在#2同时红色。如果我将文件提升为#1,然后再对其进行一些更改,则会发生这种情况。 #1中的条目引用我在推广文件之前所做的增量,可能会添加一行新代码,而#2中的条目引用我之后创建的增量,可能会在顶部添加注释。如果我更有条理,我会在将文件提升到#1之前做出所有更改,以便完全避免这种情况。)
当你运行git status
时,这些增量最后出现,如果有的话。如果你的shell支持颜色,它们将是红色的。
这些是不在最近提交中而不在#1中的所有文件。虽然在技术上增加它会改变提交的意义上的delta,但是文件可能一直存在,人们只是不希望git记录任何有关它的信息。 (在这种情况下,您应该将文件添加到.gitignore,它将停止显示在git status
中。)
创建全新文件时,它会显示在此类别中。
git add -N
?git add -N
就是让它更容易与#3三角洲合作。正如上面接受的答案中所提到的,git diff
可以让你看到你实际准备的三角洲。 Here是一套与git diff
配合使用的好命令。
git diff
仅显示#1和#2之间的差异(即#2中的增量)。
git diff --staged
只显示#1中的增量。
git diff HEAD
只显示#1和#2中的增量,放在一起。
请注意,这些命令都不会看到#3。但是,通过运行git add -N
,您基本上可以执行以下操作:
git add
将“文件创建”增量转换为#1这具有使第二个delta出现在#2中的效果。现在新文件完全超出#3,您可以使用git diff
命令。
至于git commit -a
,它的作用基本上是:
git add
#2中的所有内容,以便它也在#1中的所有内容上演git commit
(它包含#1中的所有内容,包括刚添加的内容,并从中创建实际提交)没有git add -N
,这个命令会错过你在#3中的新文件;但是,您可以看到在运行git add -N
之后,您的新文件将分布在#1和#2中,并将包含在提交中。
好吧,我已经解释了我想解释的一切。如果您想检查您的理解,可以按照以下示例进行操作:
sh-4.1$ cd ~/Desktop
sh-4.1$ mkdir git-demo
sh-4.1$ cd git-demo
sh-4.1$ git init
Initialized empty Git repository in /local/home/Michael/Desktop/git-demo/.git/
git status
告诉我这个回购是空的。
sh-4.1$ git status
On branch master
Initial commit
nothing to commit (create/copy files and use "git add" to track)
sh-4.1$ echo "this is the abc file" > abc.txt
sh-4.1$ echo "this is the def file" > def.txt
sh-4.1$ echo "this is the ghi file" > ghi.txt
git status
向我展示了所有新文件目前属于#3类。
sh-4.1$ git status
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
abc.txt
def.txt
ghi.txt
nothing added to commit but untracked files present (use "git add" to track)
git diff
什么都不做,因为它不会在#3上运行。
sh-4.1$ git diff
add -N
提交第三个文件。
sh-4.1$ git add abc.txt && git commit -m "some commit message"
[master (root-commit) 442c173] some commit message
1 file changed, 1 insertion(+)
create mode 100644 abc.txt
sh-4.1$ git add def.txt
sh-4.1$ git add -N ghi.txt
git status
,abc.txt
不再出现,因为它已经被承诺。自整个文件添加以来,def.txt
仅出现在#1类中。 ghi.txt
出现在#1和#2类别中。
sh-4.1$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: def.txt
new file: ghi.txt
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)
modified: ghi.txt
git diff
,我可以显示#2中列出的所有增量。显示的唯一增量是我向ghi.txt
添加了一条线。
sh-4.1$ git diff
diff --git a/ghi.txt b/ghi.txt
index e69de29..8a8dee2 100644
--- a/ghi.txt
+++ b/ghi.txt
@@ -0,0 +1 @@
+this is the ghi file
git diff --staged
,我可以显示#1中列出的所有增量。其中三个出现:创建一个新文件def.txt
,在def.txt
中添加一行,并创建一个新文件ghi.txt
。即使def.txt
有2个增量,文件名本身也仅在上面的例7中输出一次,以避免混乱。
sh-4.1$ git diff --staged
diff --git a/def.txt b/def.txt
new file mode 100644
index 0000000..48baf27
--- /dev/null
+++ b/def.txt
@@ -0,0 +1 @@
+this is the def file
diff --git a/ghi.txt b/ghi.txt
new file mode 100644
index 0000000..e69de29
它主要用于为您的提交添加一个空文件。
更多关于Git with intent to add!的信息。
请注意,在git 2.10(2016年第3季度)之前,git add -N
有时会跳过某些条目。
参见commit 6d6a782,commit c041d54,commit 378932d,commit f9e7d9f,Nguyễn Thái Ngọc Duy (pclouds
)(2016年7月16日)。
(Junio C Hamano -- gitster
--合并于commit 3cc75c1,2016年7月25日)
如果你有:
a-file
subdir/file1
subdir/file2
subdir/file3
the-last-file
而你add -N
一切...然后subdir
文件不记录为i-t-a(“打算添加”)条目。
cache-tree.c
:有时修复i-t-a条目跳过目录更新qazxsw poi(qazxsw poi:当qazxsw poi存在时修复写缓存树 - 2012-12-16 - Git v1.8.1.1)在从索引构建树对象时跳过i-t-a条目。不幸的是,它可能会跳过太多。
如果Commit 3cf773e是i-t-a,由于此代码中的条件破坏,我们仍然认为“
cache-tree
”是一个i-t-a文件,而不是写下“CE_REMOVE
”并跳转到最后一个文件。 结果树现在只有两个项目:subdir/file1
和subdir
。subdir
也应该在那里(尽管它只记录了两个子条目,a-file
和the-last-file
)。
subdir
已经改进,Git 2.17(2018年第二季,四年后):在工作树中移动路径(因此使其显示为“已移除”)然后添加file2
选项(因此使其显示为“已添加”), file3
将其视为重命名,但没有正确报告旧的和新的路径名。
参见git status
,-N
,git status
,commit 176ea74,commit 5134ccd,commit ea56f97,commit 98bc94e(2017年12月27日)。
帮助:commit 06dba2b。
(由commit 6de5aaf合并于Nguyễn Thái Ngọc Duy (pclouds
),2018年2月27日)。
提醒:Igor Djordjevic (boogisha
)或Junio C Hamano -- gitster
--代表“有意添加”,commit 12accdc的作用。
ita
:处理worktree重命名在
i-t-a
之前(-N
:允许ita条目被视为“索引中尚不存在” - 2016-10-24,Git 2.11.0-rc0)索引中从不存在“新文件”,这实际上禁用了重命名检测,因为我们只当新文件出现在差异对中时检测重命名。在提交之后,i-t-a条目可以在“
wt-status.c
”中显示为新文件。但425a28e中的diff回调函数不处理这种情况并产生错误的状态输出。