git添加了什么 - 添加 - 或添加 - 或者什么时候应该使用它?

问题描述 投票:22回答:4

git add -h我可以看到以下选项:

-N, --intent-to-add   record only the fact that the path will be added later

但我不明白何时应该使用此选项。这个选项真正做了什么,以及如何使用它?

git
4个回答
22
投票

启用未跟踪文件的差异化

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 --allgit 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提交它们非常有用。


4
投票

user456814's answer很好地解释了git add -N的用途。我只想更详细地解释背景中发生的事情。

您可以将git视为维护文件更改的历史记录,例如创建,修改和删除(让我们称之为增量)。在最近的提交之前,增量是非常自我解释的,但是当你在项目中工作以准备一个新的提交时,事情变得更加复杂。在这种情况下,有三种不同类型的增量。

(旁注:大多数人,当第一次介绍给git时,会被教导类似于“在git中进行需要两个步骤;首先你做git add然后你可以做git commit”。虽然这是真的,但它只会引起人们对是承诺的delta类型。了解git add -N也需要了解其他类型的增量。)

#1:要提交的更改

通常称为“分阶段更改”,当您运行git status时,这些增量会出现在顶部,如果有的话。如果你的shell支持颜色,它们将是绿色的。

当你git add文件时,它会被提升到这个类别。如果您运行没有任何标志的git commit,这些更改将实际包含在内。

#2:未提交的更改未提交

当你运行git status时,这些增量出现在第二位,如果有的话。如果你的shell支持颜色,它们将是红色的。

这些是您对git存储库中尚未提交且尚未移至#1的文件所做的更改。编辑文件然后保存时,默认情况下它将显示在此类别中。

对于要在此类别中显示的文件,必须在最近的提交中存在EITHER,或者如果要提交#1中的更改​​,则添加该文件。否则,它将出现在类别#3中。

(注意:因为您选择何时将文件“提升”到类别#1中,所以可以在#1和#2中显示相同的文件。例如,我可以看到

modified:   abc.txt

#1中的绿​​色,和

modified:   abc.txt

在#2同时红色。如果我将文件提升为#1,然后再对其进行一些更改,则会发生这种情况。 #1中的条目引用我在推广文件之前所做的增量,可能会添加一行新代码,而#2中的条目引用我之后创建的增量,可能会在顶部添加注释。如果我更有条理,我会在将文件提升到#1之前做出所有更改,以便完全避免这种情况。)

#3:未跟踪的文件

当你运行git status时,这些增量最后出现,如果有的话。如果你的shell支持颜色,它们将是红色的。

这些是不在最近提交中而不在#1中的所有文件。虽然在技术上增加它会改变提交的意义上的delta,但是文件可能一直存在,人们只是不希望git记录任何有关它的信息。 (在这种情况下,您应该将文件添加到.gitignore,它将停止显示在git status中。)

创建全新文件时,它会显示在此类别中。

So what does all this have to do with 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中,并将包含在提交中。


好吧,我已经解释了我想解释的一切。如果您想检查您的理解,可以按照以下示例进行操作:

  1. 我做了一个新的git repo。 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/
  2. git status告诉我这个回购是空的。 sh-4.1$ git status On branch master Initial commit nothing to commit (create/copy files and use "git add" to track)
  3. 我制作了一些新文件。 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
  4. 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)
  5. git diff什么都不做,因为它不会在#3上运行。 sh-4.1$ git diff
  6. 我提交一个文件,添加另一个文件,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
  7. git statusabc.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
  8. 通过运行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
  9. 通过运行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

2
投票

它主要用于为您的提交添加一个空文件。

更多关于Git with intent to add!的信息。


2
投票

请注意,在git 2.10(2016年第3季度)之前,git add -N有时会跳过某些条目。

参见commit 6d6a782commit c041d54commit 378932dcommit f9e7d9fNguyễ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/file1subdirsubdir也应该在那里(尽管它只记录了两个子条目,a-filethe-last-file)。


subdir已经改进,Git 2.17(2018年第二季,四年后):在工作树中移动路径(因此使其显示为“已移除”)然后添加file2选项(因此使其显示为“已添加”), file3将其视为重命名,但没有正确报告旧的和新的路径名。

参见git status-Ngit statuscommit 176ea74commit 5134ccdcommit ea56f97commit 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回调函数不处理这种情况并产生错误的状态输出。

© www.soinside.com 2019 - 2024. All rights reserved.