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

时间:2014-06-20 13:59:18

标签: git

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

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

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

4 个答案:

答案 0 :(得分:22)

启用未跟踪文件的差异

Blue112's answer 部分正确无误。 git add --intent-to-add确实为工作副本中的每个指定未跟踪文件的临时区域/索引添加了一个空文件,但其中一个主要目的是使您能够使用 {{ 1}} 将文件尚未添加到Git存储库,方法是将未跟踪的文件与暂存区域中的空版本区分开来:

git diff

一旦您对文件进行了差异化,您只需执行正常$ 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制作了未跟踪的文件&#34;已知&#34;通过将这些文件的空版本添加到临时区域/索引到Git,它还允许您使用--intent-to-addgit commit --all将这些文件与您已知的已修改文件一起提交,这是您不会#39; t能够做到。

正如official Linux Kernel documentation for git commit

中所述
  

使用git commit -a [或-a]开关与提交命令[将]自动&#34;添加&#34;来自所有已知文件的更改(即已在索引中列出的所有文件)...然后执行实际提交

文档

来自official Linux Kernel git add documentation

--all
     

仅记录稍后添加路径的事实。路径的条目放在索引中,没有内容。除其他外,这对于使用-N --intent-to-add 显示此类文件的非暂停内容并将其与git diff一起提交非常有用。

答案 1 :(得分:4)

user456814's answer非常清楚地解释了git add -N有用的内容。我只想更详细地解释后台发生的事情。

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

(旁注:大多数人,第一次介绍给git时,会被教授类似于&#34;提交git需要两个步骤;首先你做git add然后你可以做git commit& #34;。虽然这是真的,但它只关注要提交的更改类型的delta。理解git add -N还需要了解其他类型的增量。)

#1:要提交的更改

通常称为&#34;分阶段更改&#34;,当您运行git status时,这些增量在顶部显示 ,如果有的话。如果你的shell支持颜色,它们将是绿色的。

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

#2:未提交提交的更改

当您运行git status时,这些增量会显示,如果有的话。如果你的shell支持颜色,它们将是红色的。

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

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

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

modified:   abc.txt

在#1中为绿色,

modified:   abc.txt

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

#3:未跟踪文件

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

这些是不在最近提交但不在#1中的所有文件。虽然在技术上增加它会改变提交的意义上的增量,但是文件可能始终存在并且人们根本不希望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&#34;文件创建&#34; delta进入#1

这具有使第二个增量出现在#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 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
    
  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 :(得分:2)

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

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

答案 3 :(得分: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-有时跳过目录更新的条目

     

Commit 3cf773ecache-tree:修复在CE_REMOVE出现时写缓存树的问题 - 2012-12-16 - Git v1.8.1.1)从构建树对象时跳过一个条目指数。不幸的是,它可能会跳过太多。

     

如果subdir/file1是ita,由于此代码中的条件已损坏,我们仍然认为“subdir”是一个ita文件而不是写下“subdir”并跳转到在-最后文件。
  结果树现在只有两个项目:a-filethe-last-file   subdir也应该在那里(即使它只记录了两个子条目,file2file3)。

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

commit 176ea74点击commit 5134ccdcommit ea56f97commit 98bc94ecommit 06dba2bcommit 6de5aafNguyễn Thái Ngọc Duy (pclouds)(2017年12月27日) 。
帮助:Igor Djordjevic (boogisha)
Junio C Hamano -- gitster --于2018年2月27日commit 12accdc合并)

提醒:itai-t-a代表“有意添加”,-N的内容。

  

wt-status.c:处理worktree重命名

     

425a28e之前(diff-lib:允许将条目视为“尚不存在”   在索引“ - 2016-10-24,Git 2.11.0-rc0”中,索引中从不存在“新文件”,这实际上禁用了重命名检测,因为我们只检测新文件出现在差异对中时的重命名。

     

在提交之后,i-t-a条目可以在“git diff-files”中显示为新文件。但wt-status.c中的差异回调函数却没有   处理这种情况并产生错误的状态输出。