skip to content

In Git, how do git add -A, git add -u, and git add . differ?

level: juniorimportance: must knowfreq 68%

answer

  1. two questions, not three commands
  2. one of them never adds new files
  3. one of them cares where you are standing
  4. deletions count as changes in modern Git

basics

~20 s

In modern Git, add -A stages new, modified and deleted paths across the whole working tree; add -u stages modifications and deletions for already-tracked paths only, never new files; add . does what -A does but limited to the current directory and below.

solid answer

~50 s

All three stage changes; they differ on **scope** and on **whether untracked files count**. - `git add -A` (`--all`) stages every change in the whole working tree, regardless of your current directory: new files, modified files and deletions. - `git add -u` (`--update`) restricts itself to paths Git already tracks. Modifications and deletions are staged; brand-new untracked files are ignored. It is the safe choice when your tree contains build output you have not ignored yet. - `git add .` passes the pathspec `.`, meaning the current directory and everything under it. Within that subtree it behaves like `-A`, staging new, modified and deleted paths alike. So the real contrast is `-u` versus the other two on untracked files, and `.` versus `-A` on directory scope. You can combine them: `git add -A .` limits the all-changes behaviour to the current subtree.

code

console · 8 lines
console
$ cd src
$ git status --short
 M src/app.js
 D docs/old.md
?? src/scratch.txt
$ git add .        # stages src/app.js and src/scratch.txt only
$ git add -u       # stages tracked edits and docs/old.md, no scratch.txt
$ git add -A       # stages all three, from anywhere in the tree

go deeper

for a junior

Be able to state the two differences crisply: -u never stages untracked files, and . is limited to the current directory while -A covers the whole tree.

for a middle

Explain the two axes (untracked-or-not, scope) and the Git 2.0 change to deletion handling, and show that you check git status --short before any blanket add.

for a senior

Demonstrate the habit behind the command: blanket adds only after the untracked list is clean, ignore rules fixed at the source, and mixed work split rather than swept into one commit.

for a principal

Own the guardrails — ignore rules, secret scanning before push, and review norms — so an accidental blanket add is caught by process rather than by an individual's vigilance.

## Two independent axes Candidates usually memorise three commands and get them confused because they are really two questions asked at once. **Axis one — do untracked files count?** `-u` says no: only paths that already have an index entry are considered, so modifications and deletions are staged and a newly created file is left alone. `-A` and a plain pathspec both say yes: new files are added along with everything else. **Axis two — how much of the tree?** `-A` with no pathspec covers the entire working tree no matter where you are standing. `.` is a pathspec meaning the current directory and below, so running it from a subdirectory quietly ignores changes elsewhere in the repository. `-u` with no pathspec also covers the whole tree in modern Git. Once you see the two axes, the combinations are obvious: `git add -A .` is all-changes limited to this subtree, and `git add -u src/` is tracked-only limited to `src/`. ## The deletion trap and its history The classic confusion is whether these commands notice a file you deleted with `rm`. In Git 2.x they all do within their scope — a deletion is just another change to stage. This was not always true: older Git treated `git add .` as "add and update", silently skipping removals, which is why so much folklore still insists you must use `-A`. If you find advice claiming `git add .` misses deletions, it predates Git 2.0. Running against an old Git, or writing a script that must behave identically everywhere, is the one case where spelling out `git add -A` is worth the keystrokes. ## Choosing in practice Blanket staging is convenient and occasionally embarrassing. Two habits keep it safe. First, run `git status --short` before any blanket add and read the `??` lines. Those are the untracked files that `-A` and `.` will sweep in — a `node_modules` directory, a local dump file, an editor scratch file. If you see them, fix the ignore rules rather than reaching for `-u` as a workaround; `-u` hides the problem from this commit but not from the next person. Second, remember that these commands say nothing about what *belongs* in the commit. Staging everything at once is the opposite of composing a commit: it produces a diff with several intents in it, which reviewers and later bisects both pay for. For a mixed working tree, hunk-level staging is the tool; blanket adds are for when you have already checked that everything on the list is one change. ## Related spellings `git commit -a` is roughly `git add -u` followed by a commit — tracked modifications and deletions only, no new files. That is why a new file you forgot to add keeps missing your commits. Pathspec magic gives finer control: `git add :/` stages from the repository root regardless of your current directory, and `git add ':(exclude)*.log'` stages everything but the matching paths. Both are useful when a blanket add is nearly right but not quite.

  • Does git add . stage a file you deleted with rm?
    Yes, in Git 2.x — provided the deleted path is inside the current directory subtree. A deletion is just another change to that path. Older Git skipped removals for a plain pathspec, which is the origin of the widespread advice to always use -A; that advice predates Git 2.0.
  • What does git commit -a stage, and why does it keep missing your new files?
    It stages modifications and deletions for already-tracked paths, roughly `git add -u` followed by a commit. Untracked files have no index entry, so they are never included and a newly created file silently misses every commit until you `git add` it explicitly once.
  • You are in a subdirectory and want to stage everything in the repository. What do you run?
    `git add -A` with no pathspec covers the whole working tree from anywhere, and `git add :/` does the same by naming the repository root as the pathspec. Plain `git add .` would stage only the current directory and below.

saying these in an interview costs you the question

  • Says git add . still ignores deletions in modern Git
  • Thinks -u also picks up brand-new files
  • Believes -A and . differ on deletions rather than scope
  • Cannot say what changes when run from a subdirectory

context