skip to content

In Git, which changes does git commit -a stage, and what are its pitfalls?

level: middleimportance: should knowfreq 52%

answer

  1. tracked versus untracked matters
  2. one of the three states is skipped
  3. scope is the whole working tree
  4. selective staging is overwritten
  5. especially bad next to --amend

basics

~20 s

git commit -a automatically stages modifications and deletions of files Git already tracks, then commits. It ignores untracked files, sweeps in every unrelated edit in the working tree, and overrides any partial staging you set up for those files.

solid answer

~50 s

`-a` tells `git commit` to stage tracked files that were modified or deleted before making the commit. Three consequences bite people. First, **untracked files are not included**, so a newly created source file is silently left out and the commit can break the build for everyone else. Second, it is repository-wide: every unrelated edit sitting in your working tree lands in the same commit, which destroys the discipline of small, reviewable commits. Third, it overrides partial staging — if you carefully staged one hunk of a file with `git add -p`, `-a` replaces that with the file's entire working-tree content. The combination `git commit -a --amend` is the sharpest edge: it folds unrelated work into a previous commit without showing you a review step. Running `git status` or `git diff --cached` before committing avoids all three.

code

console · 7 lines
console
$ git status --short
 M src/Main.kt
 D src/Old.kt
?? src/NewService.kt
$ git commit -am "add new service"
[main 9f1c2ab] add new service
 2 files changed

go deeper

for a junior

Remember the headline rule: -a stages changes to files Git already tracks, and never picks up a brand-new file. Check git status for untracked entries before committing.

for a middle

Explain that -a is a shortcut for staging tracked modifications and deletions, that it is repository-wide, and that it replaces any selective staging you had set up for those files.

for a senior

Show the failure mode you have actually seen: a new file missing from a commit that broke CI, or -a --amend quietly folding unrelated work into a published commit, plus the review habit that prevents it.

for a principal

Take a position on commit hygiene as a team standard — atomic commits keep revert and bisect meaningful, and habits like blanket -a erode that far more than any tooling gap.

## What -a means `git commit -a` (often written `git commit -am "msg"`) is documented as staging files that have been **modified and deleted**, but explicitly not files Git does not yet know about. It is a convenience that collapses `git add` on tracked paths and `git commit` into one step. It does not bypass the index — Git still stages, then commits from the index. It is closer to "add every tracked change first" than to "commit the working tree". ## Pitfall 1: new files are skipped This is the most common production incident from `-a`. You create `NewService.kt`, edit three existing files, and run `git commit -am "add new service"`. The three edits are committed; the new file is not, because it is untracked. Locally everything compiles — the file is on disk. On a colleague's clone or in CI, the build fails on a missing symbol. The fix is to run `git status` first and notice the *Untracked files* section, or to use `git add -A` when you genuinely want everything including new paths. ## Pitfall 2: it is repository-wide, not path-scoped `-a` picks up tracked modifications anywhere in the working tree, not just in the directory you are standing in and not just the ones you were thinking about. A debug print you added in an unrelated module, a formatting change from your editor, a config file your tooling rewrote — all of it joins the commit. That undermines the properties you actually want from history: a commit that can be reviewed as one idea, reverted as one unit, and pointed at by bisect as the cause of one regression. You can pass pathspecs — `git commit -a -- src/` limits the automatic staging to that path — but at that point explicit `git add` is usually clearer. ## Pitfall 3: it overrides partial staging If you split a messy working file into pieces and staged only one hunk, the index and the working tree deliberately disagree for that file. `-a` re-stages the file wholesale, so the whole working-tree version is committed and the split you set up is gone. The rule of thumb: once you have staged selectively, commit **without** `-a`. ## Pitfall 4: -a combined with --amend `git commit -a --amend --no-edit` is the most dangerous combination, because it does two invisible things at once: it sweeps up unrelated tracked changes and it hides them inside a commit that already exists and already has a message describing something else. There is no editor step where you might notice the extra files. If that commit has been pushed, you have now silently changed published content. Prefer `git add <paths>` followed by `git commit --amend`, and check `git diff --cached` first. ## What -a does not do It does not remove files from the index that you deleted only from the index, it does not add ignored files, and it does not touch submodule contents beyond recording a changed submodule pointer if that pointer moved. It also does not skip hooks — `pre-commit` and `commit-msg` still run. ## Habits that make -a safe - Run `git status --short` first; anything with `??` will not be committed by `-a`. - Use `git diff --cached` after staging (or `git commit -v`, which puts the staged diff in the message editor) to review what is actually going in. - Reach for `git add -A` when "everything, including new files" is genuinely what you mean, and for explicit paths when it is not. ## Interview framing Interviewers ask this to see whether you distinguish the working tree from the index. A candidate who says "`-a` commits everything" has not internalised that Git tracks paths, and will eventually ship a commit missing a new file.

  • What is the difference between git commit -a and git add -A followed by git commit?
    `git add -A` stages everything in the working tree including new, untracked files and removals, so the resulting commit also carries files Git had never seen. `git commit -a` limits itself to paths already tracked. Both are repository-wide, so both sweep in unrelated edits; the distinction is only whether untracked paths join the commit.
  • How can you review what -a is about to commit before it happens?
    Run `git status --short` first — lines starting with `??` are untracked and will be left out. To see the content rather than the file list, stage explicitly and read `git diff --cached`, or use `git commit -v`, which puts the staged diff below the message in the editor so you review it while writing the message.

saying these in an interview costs you the question

  • Says -a commits untracked files too
  • Thinks -a bypasses the index entirely
  • Assumes -a only affects the current directory
  • Uses -a --amend routinely without reviewing the diff
  • Claims -a preserves hunks staged with add -p

context