Git Tutorial: Difference between "add -A", "add -u", "add .", and "add *"
Based on Corey Schafer's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.
Use “git add -A” (or plain “git add” on Git version 2) to stage new, modified, and deleted files across the working tree.
Briefing
Git add’s different flags all target the staging area, but they differ sharply in which kinds of changes they include: modified vs. new (untracked) vs. deleted, and whether the command is scoped to the current directory or the entire working tree. The biggest practical takeaway is that “git add -A” (or “git add” in newer Git) stages everything—new, modified, and deleted—across the whole working tree, while “git add -u” stages only modified and deleted changes and leaves new files out.
Starting from a working directory containing a mix of states—top-level deletions, top-level modifications, subdirectory deletions, subdirectory modifications, a dotfile, and both new and untracked files—the tutorial demonstrates how each syntax behaves after staging and checking with git status. “git add -A” stages modified, deleted, and new files across the entire working tree, even if the command is run from inside a subdirectory; the scope still reaches upward to include changes one directory level above. The same “all” behavior can be achieved by specifying a directory after the command (e.g., “git add -A <dir>”), which restricts staging to that directory and avoids touching changes outside it.
A key nuance: “git add -A” is also the default behavior for “git add” in Git version 2, so omitting “-A” yields the same result as “git add -A” when run from the working tree root. In Git version 1, omitting “-A” behaved differently by not staging deletions; to replicate the older behavior, the command “git add --no-all” (or “git add --ignore-removal” in the longer form) is used, which prevents deleted files from being staged.
“git add -u” (shorthand for “--update”) stages modified and deleted files but intentionally skips untracked/new files. Like “-A,” it can be scoped by adding a directory argument; running “git add -u <dir>” stages updates within that directory while leaving new files untracked and also excluding changes outside the specified directory.
The tutorial also contrasts “git add .” with “git add -A.” When run from the top-level directory, “git add .” matches “git add -A” because both effectively cover the working tree. But once inside a subdirectory, “git add .” only stages changes within the current directory, not in parent directories—so deletions and modifications one level up won’t be staged. Finally, it warns against “git add *”: the asterisk is a shell glob, not a Git-aware selector. That means it can miss deleted files (since they aren’t present on disk) and hidden dotfiles, leading to inconsistent staging results depending on where the command is run. The recommended approach is to use explicit, Git-native forms like “git add -A” or “git add -u” (optionally with a directory argument) rather than relying on shell expansion.
Cornell Notes
“git add -A” stages everything—new, modified, and deleted—across the entire working tree, even when run from a subdirectory. In Git version 2, plain “git add” defaults to the same behavior as “git add -A”; in Git version 1, omitting “-A” would skip deletions unless “--no-all” (or “--ignore-removal”) is used to force that older behavior. “git add -u” stages only modified and deleted files, skipping untracked/new files. “git add .” matches “git add -A” only when run from the repo root; inside a subdirectory it won’t stage changes in parent directories. “git add *” is discouraged because shell globbing can exclude deleted files and hidden dotfiles, producing surprising results.
What’s the practical difference between “git add -A” and “git add -u”?
Why does “git add” behave differently across Git versions?
How does scoping change the meaning of “git add -A <dir>” and “git add -u <dir>”?
When is “git add .” equivalent to “git add -A,” and when isn’t it?
Why is “git add *” considered risky?
Review Questions
- If you want to stage deletions and modifications but not new untracked files, which flag should you use: -A, -u, or .?
- What behavior changes when you run “git add .” from inside a subdirectory instead of from the repo root?
- Why can “git add *” fail to stage hidden files or deletions even when you expect “add everything” behavior?
Key Points
- 1
Use “git add -A” (or plain “git add” on Git version 2) to stage new, modified, and deleted files across the working tree.
- 2
Use “git add -u” to stage only modified and deleted files; it will not stage untracked/new files.
- 3
Adding a directory argument after “git add -A” or “git add -u” restricts staging to that directory and excludes changes outside it.
- 4
“git add .” stages changes in the current directory; it matches “git add -A” only when run from the repo root.
- 5
Avoid “git add *” because shell globbing can omit deleted files and hidden dotfiles, leading to inconsistent staging.
- 6
If you need Git version 1-style behavior that skips deletions, use “git add --no-all” (or “--ignore-removal”).