Home / Alt manpages / git-add(1)

  • git-add(1)
  • User command
  • linux

Stage the Right Changes with git add

You will finish with the intended files, or only the intended parts of files, staged for a Git commit. The examples use Git 2.43.0, installed here from the git and git-man packages. Allow about 10 minutes for the first run. You need a Git working tree and ordinary write access to it; none of these commands needs sudo.

1. Check where you are and what would change

Run this before staging anything. It separates the working tree from the index, which is Git's staging area.

$ git rev-parse --show-toplevel
/path/to/project
$ git status --short
 M src/report.py
?? notes.txt

In the short status format, ?? is an untracked file. A leading M means the index differs from the last commit; a trailing M means the working tree differs from the index. Read both columns rather than assuming that every modified file is already ready to commit.

Checkpoint

Identify the exact path or paths you intend to stage. If git rev-parse says this is not a repository, change to the correct directory or clone the project first. Do not initialise a new repository in a directory that contains the wrong project.

2. Stage one file or a named set of files

Give git add an explicit path when you want a narrow, predictable change. It records the file's content at the moment the command runs; later edits are not automatically included.

$ git add -- src/report.py notes.txt
$ git status --short
M  src/report.py
A  notes.txt

The double hyphen ends options. It is useful for a filename beginning with a hyphen, and it makes the boundary between options and paths obvious. A staged new file is shown as A in the first status column. If you edit src/report.py again, run git add -- src/report.py again to stage that later version.

For a directory, git add -- path/to/directory updates files below it, including removals. For the whole working tree, git add --all adds, modifies and removes entries everywhere. Treat that command as a broad state change: review the result before committing.

3. Review exactly what is staged

Status tells you which paths changed. The staged diff tells you what the next commit would contain.

$ git diff --cached --stat
 src/report.py | 2 +-
 notes.txt     | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)
$ git diff --cached -- src/report.py notes.txt

git diff without --cached compares the working tree with the index instead, so it answers a different question: what have you changed since staging? Use both views when you are preparing a commit with more edits still in progress.

Checkpoint

Stop if the cached diff contains credentials, private data, generated files or unrelated work. Staging does not publish anything, but a later commit or push may make those contents difficult to retract.

4. Stage only selected hunks

Use patch mode when one file contains several unrelated changes. Git presents each hunk and asks whether to stage it.

$ git add --patch -- src/report.py
diff --git a/src/report.py b/src/report.py
@@ ...
Stage this hunk [y,n,q,a,d,s,e,?]?

Use y for this hunk, n to leave it unstaged, s to split a separable hunk, and q to stop. Press ? at the prompt for the complete list. When the command ends, inspect the result:

$ git diff --cached -- src/report.py
$ git diff -- src/report.py

The first command is the proposed commit; the second is the remaining local work. This is a useful stopping point when you need to make a focused commit without hiding unfinished work.

5. Deal with ignored or missing files deliberately

Git ignores files matched by its ignore rules. An explicit ignored path fails rather than silently staging it:

$ git add -- .env
The following paths are ignored by one of your .gitignore files:
.env

Do not use force as a reflex. First check why the file is ignored and whether it contains a secret or machine-specific data. If it is genuinely safe and intentionally versioned, use the narrow command git add --force -- .env.example for the appropriate path, then inspect the cached diff. Never stage a real secret merely to make an error disappear.

To test paths without changing the index, use a dry run:

$ git add --dry-run -- path/to/file
add 'path/to/file'

A dry run is an inspection tool, not a substitute for reviewing content. Use git check-ignore -v -- path/to/file when you need the rule responsible for an ignored path.

6. Undo accidental staging without losing work

If the file is staged but the working copy is correct, remove it from the index while retaining the working-tree changes:

$ git restore --staged -- src/report.py
$ git status --short
 M src/report.py

This undo command changes the index, not the file on disk. The older spelling git reset HEAD -- path/to/file is also common, but git restore --staged states the intended operation more clearly. If you need to discard working-tree edits as well, stop and make a backup first: that is a separate, destructive action and is not required to undo staging.

7. Know the less common modes

  • git add --update -- path/to/file stages modifications and removals for paths already tracked; it does not add new files.
  • git add --intent-to-add -- new-file records that a path is intended for a later addition while leaving its content unstaged, which makes the file appear in ordinary diffs.
  • git add --renormalize --all reapplies clean filters to tracked files after changing line-ending configuration. Review the resulting diff carefully.
  • git add --chmod=+x -- script.sh changes the executable bit in the index only; it does not change the file's permissions on disk.

Use git add --sparse only when you understand the sparse-checkout boundary. Without it, Git protects paths outside the sparse-checkout cone from being updated accidentally.

Done means

  • git status --short shows the intended paths in the first column.
  • git diff --cached contains exactly the change you mean to commit.
  • Any remaining output from git diff is unfinished work you have consciously left unstaged.
  • Ignored files were investigated, not force-added by habit.
  • You know that a later edit requires another git add before committing.