ChatGPT解决这个技术问题 Extra ChatGPT

Difference between "git add -A" and "git add ."

What is the difference between git add [--all | -A] and git add .?


m
mfaani

This answer only applies to Git version 1.x. For Git version 2.x, see other answers.

Summary:

git add -A stages all changes

git add . stages new files and modifications, without deletions (on the current directory and its subdirectories).

git add -u stages modifications and deletions, without new files

Detail:

git add -A is equivalent to git add .; git add -u.

The important point about git add . is that it looks at the working tree and adds all those paths to the staged changes if they are either changed or are new and not ignored, it does not stage any 'rm' actions.

git add -u looks at all the already tracked files and stages the changes to those files if they are different or if they have been removed. It does not add any new files, it only stages changes to already tracked files.

git add -A is a handy shortcut for doing both of those.

You can test the differences out with something like this (note that for Git version 2.x your output for git add . git status will be different):

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

How about the difference between git add *?
too bad git add -A -p doesn't work as one would expect (ask interactively about untracked files)
Please update the answer. It should be: git add -A :/ or git add -A .
For information, in newer versions of git git add -u has become git add -u :/ with the latter parameter being a path, allowing you to -u certain directories, :/ handles the whole tree.
@CharlesBailey, Git really love making things complicated for no good reason. Is there a real use case whereby someone would specifically need git add -u or git add . and by doing that it makes his life easier even after accounting for the extra mental tax added to ensure that there're no sync problems? I wonder why Git doesn't furthur split add -u into two separate commands add -u1 and add-u2 whereby one works for files starting with numerals and the other for files starting with non-numerals
T
TheGeorgeous

Git Version 1.x

Command New Files Modified Files Deleted Files Description git add -A ✔️ ✔️ ✔️ Stage all (new, modified, deleted) files git add . ✔️ ✔️ ❌ Stage new and modified files only in current folder git add -u ❌ ✔️ ✔️ Stage modified and deleted files only

Git Version 2.x

Command New Files Modified Files Deleted Files Description git add -A ✔️ ✔️ ✔️ Stage all (new, modified, deleted) files git add . ✔️ ✔️ ✔️ Stage all (new, modified, deleted) files in current folder git add --ignore-removal . ✔️ ✔️ ❌ Stage new and modified files only git add -u ❌ ✔️ ✔️ Stage modified and deleted files only

Long-form flags:

git add -A is equivalent to git add --all

git add -u is equivalent to git add --update

Further reading:

Git for beginners: The definitive practical guide

Resources to learn Git

Learn Git Branching

Explain Git With D3


Thanks for the table. Is there a way to add only the files that were modified. No new files or deleted files
@Gokul: According to this post, you can use git diff-files -z --diff-filter=M --name-only | xargs -0 git add to add only the modified files, but not the new files or the deletions.
This is not entirely true, as git add . only adds new files that are on the current path. I.e. if you have a new directory ../foo, git add -A will stage it, git add . will not.
So, git add . is equivalent to git add -A ., which is equivalent to git add "*"
This should be the top/selected/pinned answer. @cmcginty if you're still out there, after 12 years
R
Robin A. Meade

With Git 2.0, git add -A is default: git add . equals git add -A ..

git add is the same as "git add -A " now, so that "git add dir/" will notice paths you removed from the directory and record the removal. In older versions of Git, "git add " ignored removals. You can say "git add --ignore-removal " to add only added or modified paths in , if you really want to.

git add -A is like git add :/ (add everything from top git repo folder).
Note that git 2.7 (Nov. 2015) will allow you to add a folder named ":"!
See commit 29abb33 (25 Oct 2015) by Junio C Hamano (gitster).

Note that starting git 2.0 (Q1 or Q2 2014), when talking about git add . (current path within the working tree), you must use '.' in the other git add commands as well.

That means:

"git add -A ." is equivalent to "git add .; git add -u ."

(Note the extra '.' for git add -A and git add -u)

Because git add -A or git add -u would operate (starting git 2.0 only) on the entire working tree, and not just on the current path.

Those commands will operate on the entire tree in Git 2.0 for consistency with "git commit -a" and other commands. Because there will be no mechanism to make "git add -u" behave as if "git add -u .", it is important for those who are used to "git add -u" (without pathspec) updating the index only for paths in the current subdirectory to start training their fingers to explicitly say "git add -u ." when they mean it before Git 2.0 comes. A warning is issued when these commands are run without a pathspec and when you have local changes outside the current directory, because the behaviour in Git 2.0 will be different from today's version in such a situation.


@NickVolynkin That's great! Glad to see the international community of SO working as intended. For reference: ru.stackoverflow.com/a/431840
@VonC, Nice, the Git folks actually had the cheek to say their update will "make things more consistent". What they had done is created more confusion and inconsistencies. There's 26 alphabets and they had to reuse a flag that's already been used.
P
Peter Mortensen

From Charles' instructions, after testing my proposed understanding would be as follows:

# 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

This blog post might also be helpful to understand in what situation those commands may be applied: Removing Deleted Files from your Git Working Directory.


this is no longer true in 2.0. add . equals to add -A for the same path, the only difference is if there are new files in other paths of the tree
P
Peter Mortensen

Things changed with Git 2.0 (2014-05-28):

-A is now the default

The old behavior is now available with --ignore-removal.

git add -u and git add -A in a subdirectory without paths on the command line operate on the entire tree.

So for Git 2 the answer is:

git add . and git add -A . add new/modified/deleted files in the current directory

git add --ignore-removal . adds new/modified files in the current directory

git add -u . adds modified/deleted files in the current directory

Without the dot, add all files in the project regardless of the current directory.


I don't think this is correct. Using git v2.10.windows.2 'git add' returns 'Nothing specified, nothing added'. 'git add -A' adds all changed files. Which suggests '-A' is not the default.
Last point "Without the dot, add all files in the project regardless of the current directory." doesn't work. When I say {code}git add{code} (without .) then for a mesage with hint specifying if I want to say {code}git add . {code}
s
simhumileco

In Git 2.x:

If you are located directly at the working directory, then git add -A and git add . work without the difference.

If you are in any subdirectory of the working directory, git add -A will add all files from the entire working directory, and git add . will add files from your current directory.

And that's all.


P
Peter Mortensen

A more distilled quick answer:

Does both below (same as git add --all)

git add -A

Stages new + modified files

git add .

Stages modified + deleted files

git add -u

Hello, what if you just wanted to stage only modified files? How would you do that?
Hello, well good question. There isn't an easy flag for that as far as i know.. git diff-files -z --diff-filter=M --name-only | xargs -0 git add from -> stackoverflow.com/questions/14368093/…
Actually it's git add :/ + git add -u :/
P
Peter Mortensen

Both git add . and git add -A will stage all new, modified and deleted files in the newer versions of Git.

The difference is that git add -A stages files in "higher, current and subdirectories" that belong to your working Git repository. But doing a git add . only stages files in the current directory and subdirectories following it (not the files lying outside, i.e., higher directories).

Here's an example:

/my-repo
  .git/
  subfolder/
    nested-file.txt
  rootfile.txt

If your current working directory is /my-repo, and you do rm rootfile.txt, then cd subfolder, followed by git add ., then it will not stage the deleted file. But doing git add -A will certainly stage this change no matter where you perform the command from.


P
Peter Mortensen

git add . equals git add -A . adds files to index only from current and children folders.

git add -A adds files to index from all folders in working tree.

P.S.: information relates to Git 2.0 (2014-05-28).


P
Peter Mortensen

I hope this may add some more clarity.

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

Limiters may be -u or -A or nil.

Pathspec may be a filepath or dot, '.' to indicate the current directory.

Important background knowledge about how Git 'adds':

Invisible files, those prefixed with a dot, (dotfiles) are never automatically recognized by Git. They are never even listed as 'untracked'.

Empty folders are never added by Git. They are never even listed as 'untracked'. (A workaround is to add a blank file, possibly invisible, to the tracked files.)

Git status will not display subfolder information, that is, untracked files, unless at least one file in that subfolder is tracked. Before such time, Git considers the entire folder out of scope, a la 'empty'. It is empty of tracked items.

Specifying a filespec = '.' (dot), or the current directory, is not recursive unless -A is also specified. Dot refers strictly to the current directory - it omits paths found above and below.

Now, given that knowledge, we can apply the answers above.

The limiters are as follows.

-u = --update = subset to tracked files => Add = No; Change = Yes; Delete = Yes. => if the item is tracked.

-A = --all (no such -a, which gives syntax error) = superset of all untracked/tracked files , unless in Git before 2.0, wherein if the dot filespec is given, then only that particular folder is considered. => if the item is recognized, git add -A will find it and add it.

The pathspec is as follows.

In Git before 2.0, for the two limiters (update and all), the new default is to operate on the entire working tree, instead of the current path (Git 1.9 or earlier),

However, in v2.0, the operation can be limited to the current path: just add the explicit dot suffix (which is also valid in Git 1.9 or earlier);

git add -A .

git add -u .

In conclusion, my policy is:

Ensure any hunks/files to be added are accounted for in git status. If any items are missing, due to invisible files/folders, add them separately. Have a good .gitignore file so that normally only files of interest are untracked and/or unrecognized. From the top level of the repository, "git add -A" to add all items. This works in all versions of Git. Remove any desired items from the index if desired. If there is a big bug, do 'git reset' to clear the index entirely.


P
Peter Mortensen

The -A option adds, modifies, and removes index entries to match the working tree.

In Git 2 the -A option is now the default.

When a . is added that limits the scope of the update to the directory you are currently in, as per the Git documentation

If no is given when -A option is used, all files in the entire working tree are updated (old versions of Git used to limit the update to the current directory and its subdirectories).

One thing that I would add is that if the --interactive or -p mode is used then git add will behave as if the update (-u) flag was used and not add new files.


G
Good Pen

I hate the staging mechanism of git, which can not be found in other SCM tools. So I always use:

\git add --all && \git commit --all

(Even though with \git add --all, \git commit is enough)

for add:

--no-ignore-removal  --all     | add, modify, and remove index entries to match the working tree
--ignore-removal     --no-all  | add, modify             index entries to match the working tree

--intent-to-add                | add an entry for the path to the index,  with no content

-A is short for --all

git add equals to:

for version 2.35.1 of Git: git add --all <pathspec>
Older versions of Git: git add --no-all <pathspec>

But git add followed by nothing, does not equal to git add --all, and will do nothing:

https://i.stack.imgur.com/2Nb4w.png

git add --all(omitting <pathspec>): handle all files in the entire working tree (old versions of Git used to limit the update to the current directory and its subdirectories).

git commit --all

Tell the command to automatically stage files that have been modified and deleted,. new files you have not told Git about are not affected