Git and GitHubgit 2.54 · GitHub · macOS, Linux or Windows
Dashboard
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
26 small wins to finish your pathNext lesson →

Staging and committing

The staging area is the list of changes Git will put in your next commit: git add writes to that list, and git commit turns the list into a snapshot that is kept forever.

Last updated: 12 Oct, 2026 · git 2.54

This is the one idea that makes every later command readable. A change you make lives in three places in turn, and each Git command moves it from one to the next. Read this page slowly; the rest of the course assumes it.

The three places a change lives on your own machine. The working tree is the folder you edit. git add copies a change from the working tree into the staging area, and git restore --staged takes it back out. git commit turns everything in the staging area into a commit in the local repository. git restore throws away a change in the working tree.

The three states, in words

  • The working tree is the folder as it is now. Saving a file in your editor changes the working tree and leaves the other two alone.
  • The staging area is a list Git keeps of the changes you have chosen for the next commit. Git's own documentation also calls it the index.
  • The local repository is the set of commits inside .git. A commit is never changed once it is made.

Two commands move work forward. git add copies the current content of a file into the staging area. git commit takes everything in the staging area, writes it into the repository as one commit, and empties the list.

Tracking a file with git add and what the staging area is · from the Git and GitHub series · 7:59 to 9:19

Syntax: name the paths you want staged, then commit with a message.

bash
git add <path>              # one file, a folder, or . for everything below you
git commit -m "<message>"   # everything staged becomes one commit
Project files used on this pageThis lesson builds on a project from earlier lessons. The code below imports this file. Click a file to see its code, or follow the link to the lesson that wrote it. To run the code yourself, keep it in the same folder.
View the code here
.gitconfig
[user]
	name = Reader
	email = reader@example.com

Status before anything is tracked

Start with one file in a fresh repository. Git has never seen it, so it calls the file untracked: it exists in the working tree and nowhere else.

ExampleA file Git has not been told about
mkdir ask-docs && cd ask-docs
git init -q -b main
printf 'Support bot\n' > README.md    # create the file
git status

printf writes a line into a file, which is the same as typing it in an editor and saving. The answer lists README.md under Untracked files and ends with nothing added to commit, because an untracked file is not part of the next commit.

Those first three lines are the throwaway repository for the rest of this page. Every block below starts from them and shows only the command it is teaching.

Staging the file with git add

git add with a path copies that file into the staging area.

ExampleThe same file after one git add
git add README.md
git status
  • Changes to be committed is the staging area printed as a list.
  • new file: README.md means the whole file is new to Git, not only its latest lines.
  • The hint about git rm --cached is Git telling you how to take it back out. Current Git has a clearer command for that, further down this page.

Making the first commit

git commit -m turns the staged list into a commit. The -m is the message, in quotes; without it Git opens an editor and waits.

Git stores a date with each commit, and reads it from the GIT_AUTHOR_DATE and GIT_COMMITTER_DATE variables when they are set. The examples set them to one fixed moment so every run produces the same commit and the hashes below match what you see. Leave them out in your own work and Git uses the clock.

ExampleThe first commit
# the same two dates every run, so the commit hashes below match
export GIT_AUTHOR_DATE="2026-10-12T10:00:00+00:00"
export GIT_COMMITTER_DATE="2026-10-12T10:00:00+00:00"
git commit -m "Add a README for the docs assistant"
  • [main (root-commit) ...] names the branch, says this is the first commit in the repository, and prints the short hash that identifies it.
  • 1 file changed, 1 insertion(+) counts what went in: one file, one line.
  • create mode 100644 README.md records that the file is new and is an ordinary non-executable file.

The commit is made, so the three places now hold the same content. Status says so in two lines.

ExampleStatus after the commit
git status

nothing to commit, working tree clean is the status Git reports when the working tree, the staging area and the last commit all hold the same content.

Staging several changes with git add .

A real commit usually touches more than one file. git add . stages everything that changed in the folder you are standing in and below it, new files included.

ExampleOne modified file and one new file, staged together
printf 'Support bot\n\nAnswers questions from your own documents.\n' > README.md   # change it
printf 'chunk_size = 500\n' > loader.py   # and write a new file
git add .
git status
  • modified: README.md is a file Git already tracks, with new content staged.
  • new file: loader.py is a file Git had never seen before this git add ..
  • The dot in git add . means this folder and everything below it, so a file in a subfolder is staged too.

The two changes commit together, so the history gets one commit holding both. Keep a commit to one piece of work: a reader later should be able to say what it was for.

The change you staged is the change you commit

git add copies the file as it is at that moment. Edit the file again and the new edit is not staged, so the commit would carry the older content. Git shows the file twice when that happens, and beginners read that as a bug.

ExampleThe same file staged and modified at once
printf 'Answers from your own documents.\n' >> README.md   # one change
git add README.md
printf 'Run it with python loader.py\n' >> README.md       # a second change, after staging
git status

README.md is listed under both headings. Changes to be committed holds the first edit, and Changes not staged for commit holds the second. Committing now would keep the first edit and leave the second out. Running git add README.md again stages the newer content and the file leaves the second list.

Taking a change back out of the staging area

git restore --staged <path> removes a file from the staging area and leaves your edit alone. Older material uses git reset <path> for this, which still works; git restore arrived in Git 2.23 and is the current way.

ExampleUnstaging a file without losing the edit
git restore --staged README.md    # unstage, keep the edit
git status

The file moves from Changes to be committed to Changes not staged for commit. The edit is still in the file; only Git's list changed. git restore README.md without --staged is the dangerous one: it throws the edit away and gives you back the committed content.

Working tree compared with staging area and repository

Working treeStaging areaLocal repository
What it holdsthe files as you edit themthe changes chosen for the next commitevery commit ever made
Where it livesthe project folderinside .git, as the indexinside .git, as objects
Put something insave in your editorgit addgit commit
Take something outgit restore <path>git restore --staged <path>nothing, a commit stays
Shown by status underChanges not staged for commitChanges to be committednothing, it is the baseline

Where the staging area earns its keep

  • Two unrelated fixes in one sitting. Stage and commit the first file, then the second, and the history keeps them apart.
  • A file you do not want in the commit. A scratch note next to real work stays unstaged and out of the snapshot.
  • Reviewing yourself. git status before every commit is a last look at what you are about to record.
Watch out. git commit commits the staging area, not your folder. If you forget the git add, Git answers no changes added to commit and makes nothing, and if you staged an older version of the file, that older version is what the commit keeps. Read git status before you commit.
Try it yourself
  • Stage a file, then run git commit with no -m. Git opens your editor; type a line, save and close it, and read what Git prints.
  • Make two files and stage only one with git add prompt.txt. Commit, then run git status and find the other one.
  • Edit a committed file, run git restore README.md, and open the file. The edit is gone, which is the point of being careful with that command.

Slow is fine. Stopping is the only problem.