Staging Changes

git add moves changes into the staging area — the draft of your next commit. Staging lets you decide exactly what goes into each commit, so one commit can hold one logical change even if you've been editing many files at once.

Adding a file

$
git status -s
Output
?? granola.txt
?? omelette.txt
?? pancakes.txt
$
git add pancakes.txt
git status -s
Output
A  pancakes.txt
?? granola.txt
?? omelette.txt

git add prints nothing when it works. pancakes.txt is now staged (A for added); the other two are still untracked.

Several files, folders and patterns

You can list several files, a folder (which adds everything inside it), or a wildcard pattern:

$
git add omelette.txt granola.txt
git status -s
Output
A  granola.txt
A  omelette.txt
A  pancakes.txt
$
git add src/              # everything in the src folder
git add "*.txt"           # every .txt file, in all folders (quote the pattern)

Adding everything

The most common forms add all changes at once:

CommandStages
git add .New, modified and deleted files in the current folder and below
git add -A (--all)New, modified and deleted files in the whole repository
git add -u (--update)Modified and deleted files only — new files stay untracked

Run from the top folder, git add . and git add -A do the same thing. They're convenient, but check git status first so you don't stage a stray log file or password by accident — the .gitignore file in lesson 14 prevents most of these accidents.

$
echo "Pancakes: flour, milk, eggs, sugar" > pancakes.txt
echo "Shakshuka: eggs, tomatoes, peppers" > shakshuka.txt
git add -u
git status -s
Output
M  pancakes.txt
?? shakshuka.txt

-u staged the modified pancakes.txt but left the new shakshuka.txt untracked.

Unstaging

Staged something by mistake? git restore --staged takes it back out of the staging area. Your edits in the working tree are not touched:

$
git add shakshuka.txt
git restore --staged pancakes.txt
git status -s
Output
 M pancakes.txt
A  shakshuka.txt

In older tutorials you'll see git reset HEAD <file> for this. It still works; git restore was added in Git 2.23 to give this job a clearer name.

Staging part of a file

Sometimes one file contains two unrelated edits — a bug fix and a new feature, say — and you want them in separate commits. git add -p (--patch) walks through each changed section of the file, called a hunk, and asks what to do with it:

$
git add -p pancakes.txt
KeyAction
yStage this hunk
nSkip it
sSplit it into smaller hunks
eEdit the hunk by hand
qQuit; hunks you've already answered keep their choice
?Show help

Most code editors offer the same thing graphically: select some lines in the Git panel and choose "Stage selected ranges".

Seeing what's staged

git status lists files; to see the actual lines that will be committed, use git diff --staged (lesson 12):

$
git add pancakes.txt
git diff --staged pancakes.txt
Output
diff --git a/pancakes.txt b/pancakes.txt
index a05992e..fe8185b 100644
--- a/pancakes.txt
+++ b/pancakes.txt
@@ -1 +1 @@
-Pancakes: flour, milk, eggs
+Pancakes: flour, milk, eggs, sugar

Empty folders aren't tracked

Git tracks files, not folders. A folder with nothing in it never shows up in git status:

$
mkdir photos
git status -s
Output
M  pancakes.txt
A  shakshuka.txt

If a project needs an empty folder to exist (for example a place for uploads), the convention is to put an empty file called .gitkeep inside it. The name has no special meaning to Git — any file would do.

$
touch photos/.gitkeep
git status -s
Output
M  pancakes.txt
A  shakshuka.txt
?? photos/

Try it yourself

Create three files, stage two of them with one git add command, then unstage one with git restore --staged. Predict the output of git status -s before running it.