"git add -A" 和 "git add ." 的区别是什么?

3431
12个回答

4842

此回答仅适用于Git版本1.x。有关Git版本2.x的信息,请参阅其他答案。


概要:

  • git add -A会将所有更改都加入暂存区

  • git add . 会将新文件和修改加入暂存区,但不包括删除(仅在当前目录及其子目录中)。

  • git add -u会将修改和删除加入暂存区,但不包括新文件。


详情:

git add -A 等同于 git add .; git add -u

关于 git add . 的重要一点是,它查看工作目录并将所有更改或新添加的路径添加到已缓存的更改中,但不会将任何“rm”操作添加到暂存区中。

git add -u 查看所有已经跟踪的文件,并将对这些文件所做的更改加入暂存区,如果已删除,则也将其加入。它不会添加任何新文件,只会将已跟踪文件的更改加入暂存区。

git add -A 是这两者的一个方便快捷方式。

您可以通过以下方式测试它们之间的差异(请注意,对于Git版本2.x,git add . git status 的输出将不同):

git init
echo Change me > change-me
echo Delete me > delete-me
git add change-me delete-me
git commit -m initial

echo OK >> change-me
rm delete-me
echo Add me > add-me

git status
# Changed but not updated:
#   modified:   change-me
#   deleted:    delete-me
# Untracked files:
#   add-me

git add .
git status

# Changes to be committed:
#   new file:   add-me
#   modified:   change-me
# Changed but not updated:
#   deleted:    delete-me

git reset

git add -u
git status

# Changes to be committed:
#   modified:   change-me
#   deleted:    delete-me
# Untracked files:
#   add-me

git reset

git add -A
git status

# Changes to be committed:
#   new file:   add-me
#   modified:   change-me
#   deleted:    delete-me

56
git add * 与其他 git add 命令有何不同? - Jared
3
很遗憾git add -A -p不能像人们期望的那样工作(交互式地询问未被追踪的文件)。 - Erik Kaplun
2
请更新答案。应该是:git add -A :/git add -A . - Gabriel Llamas
6
请注意,在较新版本的 Git 中,git add -u 已经变成了 git add -u :/,其中后面的参数是路径,允许您更新某些目录,而 :/ 则处理整个树。 - Brizee
21
@CharlesBailey,Git似乎真的很喜欢无缘无故地把事情搞得复杂。是否存在真正的用例,使某人需要特别使用git add -ugit add .,并且即使考虑到增加的心理负担以确保没有同步问题后,这样做也会让他的生活更轻松?我想知道为什么Git不进一步将add -u分成两个单独的命令add -u1add-u2,其中一个适用于以数字开头的文件,另一个适用于以非数字开头的文件。 - Pacerier
显示剩余16条评论

1323
✔️ Stage modified and deleted files only

Git Version 1.x

命令 新文件 修改文件 删除文件 描述
git add -A ✔️ ✔️ ✔️ 将所有(包括新增、修改和删除)的文件加入到暂存区
git add . ✔️ ✔️ 只将当前文件夹中的新增和修改文件加入到暂存区
git add -u ✔️ ✔️ 只将修改和删除的文件加入到暂存区

Git Version 2.x

命令 新文件 修改文件 删除文件 描述
git add -A ✔️ ✔️ ✔️ 将所有(包括新增、修改和删除)的文件加入到暂存区
git add . ✔️ ✔️ ✔️ 将当前文件夹中所有(包括新增、修改和删除)的文件加入到暂存区
git add --ignore-removal . ✔️ ✔️ 只将当前文件夹中的新增和修改文件加入到暂存区
git add -u ✔️ ✔️ 只将修改和删除的文件加入到暂存区
✔️ 仅添加和修改过的文件

长格式标志:

  • git add -A 等同于 git add --all
  • git add -u 等同于 git add --update

更多阅读:


3
谢谢提供表格。是否有方法只添加被修改的文件,而不包括新文件或已删除的文件? - Gokul N K
3
根据这篇文章(https://dev59.com/ymYq5IYBdhLWcg3wkRi_#14368373),您可以使用“git diff-files -z --diff-filter=M --name-only | xargs -0 git add”命令仅添加修改过的文件,但不包括新文件或被删除的文件。 - Ville
123
这并不完全正确,因为"git add ."只会添加当前路径下的新文件。也就是说,如果有一个新目录"../foo","git add -A"会将其暂存,而"git add ."则不会。 - Milo Wielondek
4
所以,git add . 相当于 git add -A .,它们也等同于 git add "*" - flow2k
2
这应该是最佳/选定/固定的答案。 @cmcginty 如果你还在,已经过去12年了。 - Spoderman4
显示剩余2条评论

211
使用Git 2.0,git add -A是默认选项:git add .相当于git add -A .

git add <path> 现在与 "git add -A <path>" 相同,因此 "git add dir/" 将会注意到您从目录中删除的路径并记录其删除。
在旧版本的 Git 中,"git add <path>" 忽略了已删除的路径。

如果确实需要这样做,可以使用 "git add --ignore-removal <path>" 仅添加已添加或修改的路径 <path>

git add -A 就像 git add :/添加顶级 git 仓库文件夹中的所有内容)。
请注意,git 2.7(2015 年 11 月)将允许您添加名为 ":" 的文件夹!
请参见 提交 29abb33(2015 年 10 月 25 日),作者是 Junio C Hamano (gitster)


请注意,从开始的git 2.0(2014年第一季度或第二季度)开始,在谈论git add .(工作树中的当前路径)时,您必须在其他git add命令中也使用'.'。
这意味着:
git add -A .”等同于“git add .; git add -u .
(请注意git add -Agit add -u的额外'.')
因为git add -Agit add -u将操作(仅限于从git 2.0开始)整个工作树,而不仅仅是当前路径。
这些命令将在Git 2.0中对整个树进行操作,以保持与“git commit -a”和其他命令的一致性。由于没有机制可以使“git add -u”表现得像“git add -u .”,因此对于那些习惯于“git add -u”(不带路径规范)仅更新当前子目录中的路径索引的人来说,在Git 2.0到来之前,开始训练自己明确地说“git add -u .”。当这些命令在没有路径规范且您拥有当前目录以外的本地更改时运行时,会发出警告,因为在Git 2.0中,这种情况下的行为与今天的版本不同。

3
@NickVolynkin 很棒!很高兴看到 Stack Overflow 的国际社区正如旨在运作。供参考:http://ru.stackoverflow.com/a/431840 - VonC
@VonC,不错,Git的人竟然有脸说他们的更新会“使事情更加一致”。他们所做的是制造更多的混乱和不一致。英文字母有26个,他们必须重复使用已经被使用过的标志。 - Pacerier

153

根据Charles的说明,经过测试后我的理解如下:

# For the next commit
$ git add .   # Add only files created/modified to the index and not those deleted
$ git add -u  # Add only files deleted/modified to the index and not those created
$ git add -A  # Do both operations at once, add to all files to the index

这篇博客也可能有助于理解在哪种情况下可以应用这些命令:从Git工作目录中删除已删除的文件

这在2.0版本已经不再适用。对于相同路径,add .等同于add -A,唯一的区别是树的其他路径中是否有新文件。


49

Git 2.0 (2014-05-28)的变化:

  • -A现在是默认选项
  • 旧的行为现在可以使用--ignore-removal选项。
  • git add -ugit add -A对于没有路径的子目录将会操作整个树。

因此,对于Git 2:

  • git add .git add -A .会添加当前目录中新的/修改过的/已删除的文件
  • git add --ignore-removal .会添加当前目录中新的/修改过的文件
  • git add -u .会添加当前目录中修改过的/已删除的文件
  • 不带点号会将项目中所有文件都添加进来,不管当前目录位置在哪里。

5
我不认为这是正确的。使用git v2.10.windows.2,'git add'返回'未指定任何内容,未添加任何内容'。 'git add -A'将添加所有更改的文件。这表明'-A'不是默认选项。 - Neutrino
最后一点“没有点,将项目中所有文件添加到当前目录之外。”不起作用。当我输入{code}git add{code}(没有点)时,会出现提示信息,询问我是否要输入{code}git add . {code}。 - user85

49

Git 2.x 版本中:

  • 如果你正位于 工作目录 中,那么 git add -Agit add . 的作用是相同的。

  • 如果你位于 工作目录 中的任何子目录中,git add -A 将会添加整个 工作目录 中的所有文件,而 git add . 则会添加当前目录下的文件。

以上就是全部内容。


40

更简洁的快速回答:

这两者都等同于git add --all

git add -A

分阶段提交新的和修改过的文件

git add .

修改的阶段+已删除的文件

git add -u

5
你好,如果只想暂存修改过的文件,应该怎么做? - TheGrapeBeyond
2
你好,这是一个很好的问题。据我所知,没有一个简单的标志来解决这个问题... git diff-files -z --diff-filter=M --name-only | xargs -0 git add 来自 -> https://dev59.com/ymYq5IYBdhLWcg3wkRi_ - K. Kilian Lindberg
4
实际上,这是将 git add :/git add -u :/ 结合起来使用。 - Nick Volynkin

15

无论是 git add . 还是 git add -A 都会在较新版本的Git中将所有新文件、修改过的文件和已删除文件都标记为staged。

不同之处在于,git add -A 会将属于您工作Git仓库的“更高级别、当前和子目录”的文件标记为staged。而使用 git add . 只会标记当前目录及其子目录中的文件(不包括位于外部的文件,即更高级别的目录)。

以下是一个示例:

/my-repo
  .git/
  subfolder/
    nested-file.txt
  rootfile.txt
如果您的当前工作目录是/my-repo,并且您执行rm rootfile.txt,然后执行cd subfolder,接着执行git add .,那么它将不会将已删除的文件添加到您的提交中。但是,执行git add -A将无论在哪里执行该命令,都会将此更改添加到您的提交中。

14

git add . 等同于 git add -A .,只把当前目录和子目录下的文件加入到暂存区。

git add -A 把工作树中所有目录下的文件都加入到暂存区。

P.S.: 信息来源于Git 2.0(2014-05-28)。


13

我希望这能增加一些清晰度。

!The syntax is
git add <limiters> <pathspec>
! Aka
git add (nil/-u/-A) (nil/./pathspec)

限定符可能是 -u 或 -A 或 nil。

路径规范可以是文件路径或点,'.' 表示当前目录。

关于 Git '添加' 的重要背景知识:

  • 不可见的文件,以点为前缀的文件(点文件),永远不会被Git自动识别。它们甚至不会列为“未跟踪”。
  • 空文件夹永远不会被Git添加。他们甚至不会被列为“未跟踪”。(一种解决方法是将一个空文件(可能不可见)添加到已跟踪的文件中。)
  • 除非该子文件夹中至少有一个文件被跟踪,否则Git状态将不显示子文件夹信息,即未跟踪的文件。在此之前,Git将整个文件夹视为不相关,类似于“空白”。它是空的跟踪项。
  • 如果未指定-A,则指定文件规范 = '.'(点),或当前目录,不具有递归性。Dot严格指当前目录-省略了上面和下面发现的路径。

现在,有了这些知识,我们可以应用上述答案。

限制器如下:

  • -u = --update = 子集,跟踪的文件=>添加=否;更改=是;删除=是。=> 如果该项被跟踪。
  • -A = --all(没有这样的-a,这会导致语法错误)=所有未跟踪/已跟踪文件的超集,除非在Git 2.0之前,如果给出了点文件规范,则仅考虑该特定文件夹。=> 如果识别该项,则git add -A将找到它并添加它。

路径规范如下。

  • 在 Git 2.0 之前,对于这两个限制器(更新和全部),新的默认设置是在整个工作树上操作,而不是在当前路径上(Git 1.9 或更早版本)。
  • 但是,在 v2.0 中,操作可以限制为当前路径:只需添加显式的点后缀(在 Git 1.9 或更早版本中也有效);

git add -A .

git add -u .

总之,我的策略是:

  1. 确保要添加的任何块/文件在git status中都有记录。
  2. 如果由于不可见文件/文件夹而缺少任何项目,请单独添加它们。
  3. 拥有一个很好的.gitignore文件,以便通常只有感兴趣的文件未跟踪和/或未识别。
  4. 从存储库的顶层,“git add -A” 添加所有项。 这适用于所有Git版本。
  5. 如果需要,从索引中删除任何所需的项目。
  6. 如果出现大问题,请使用'git reset'完全清除索引。

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