Chapter 3 of 10 · Git and GitHub for Beginners — Complete Free Tutorial

Staging and Committing

This third chapter of the Git and GitHub for Beginners series covers the daily rhythm of Git: editing files, staging the changes you want, and committing them as a permanent snapshot. Understanding the two-step stage-then-commit design is what separates people who trust their history from people who fear it.

Three areas, one workflow

Every change you make lives in one of three places. Learning to name them makes every later command obvious, because each command simply moves changes between areas.

AreaWhat it holdsTypical command
Working treeThe files you actually edit in your editoredit, save
Staging area (index)The draft of your next snapshot — changes you chose to recordgit add
Repository (.git)Every committed snapshot, safe forevergit commit

The staging area is Git's most distinctive idea. It lets you craft a commit deliberately: fix a typo in one file, stage only that fix, commit it, then stage something else. Two steps by design — stage deliberately, commit intentionally.

Staging changes with git add

git add copies changes from the working tree into the staging area. Pass a filename to stage one file, or use git add . to stage everything that changed in the current folder. After staging, run git diff --staged to review exactly what your next commit will contain — this preview is the whole point of staging. If something looks wrong, unstage it with git restore --staged <file> and nothing is lost.

Writing commit messages that help

A commit message is a note from your present self to your future team. Treat it as part of the change, not paperwork. The conventions that hold up best are simple:

  • Use the imperative mood — “Add price filter”, not “Added” or “Adds”. Read it as “This commit will …”.
  • Keep the subject short — around 50 characters, one line, no trailing period.
  • Explain the why, not the what — the diff already shows what changed; the message should explain the reason.
  • Separate subject from body with a blank line if you need more detail for a complex change.

Creating the commit

git commit takes everything staged and writes it as a new snapshot with you as author. With -m you supply the message inline; without it, Git opens your configured editor so you can write a subject and a body. When the commit finishes, Git prints the branch, the new short hash, and a summary of the change — your proof that history grew by one link. Commit small and often: a commit that changes three related lines is far easier to review, revert and understand than one that rewrites a whole file.

Checking what just happened

After committing, two commands confirm the result. git status should report a clean working tree, and git log --oneline lists history newest first, each commit on one line with its hash and message. If status still shows changes, you edited a file after staging it — stage it again and commit a second time, or amend (covered in Correcting History).

git add index.html bakery-menu.txt
git status

Expected output:

On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	new file:   index.html
	modified:   bakery-menu.txt
git commit -m "Add homepage and update the menu prices"

Expected output:

[main a1b2c3d] Add homepage and update the menu prices
 2 files changed, 34 insertions(+), 6 deletions(-)
 create mode 100644 index.html
git log --oneline

Expected output:

a1b2c3d Add homepage and update the menu prices
9f8e7d6 Save work in progress on the contact form
b2a1f0e Initial commit

Common mistakes

  • Committing everything blindly with git add -A — debug logs, screenshots and secrets slip into history unnoticed. Stage by path instead.
  • Vague messages like “fix” or “updates” — they tell your future self nothing; describe the purpose of the change.
  • Skipping the staging area and committing partial edits — you record a broken intermediate state that does not even run.
  • One giant commit per day — large snapshots are hard to review, hard to revert and hard to blame.
  • Committing generated files — node_modules, dist and .env belong in .gitignore, not in history.

Practice checklist

  1. In your practice repository, create a file and run git status to see it listed as untracked.
  2. Stage it with git add, then run git status again and find it under “Changes to be committed”.
  3. Run git diff --staged and read the plus and minus lines of your own change.
  4. Commit with a short imperative message, then confirm with git log --oneline.
  5. Intentionally stage a second file, unstage it with git restore --staged, and verify it returns to “Changes not staged”.

What's next?

History only becomes useful when you can read and rewind it. Continue to Viewing History and Undoing Changes, and if you are building pages as you learn, keep them semantic and findable with HTML & SEO.

Quiz: Staging and Committing

5 questions · 70% to pass

Frequently Asked Questions

Git is a distributed version control system: it records snapshots of your project over time, lets you jump back to any point, branch off to try ideas safely, and merge other people's work. It is the industry standard — nearly every developer job assumes basic Git fluency — and it is the best insurance you can have against lost or broken code.

Git is the tool that runs on your machine and stores history locally; it works fully offline. GitHub is one of many websites (GitLab, Bitbucket) that hosts Git repositories in the cloud and adds collaboration features: pull requests, code review, issues and CI. You can use Git forever without GitHub — GitHub needs Git to be useful.

A repository (repo) is your project folder plus a hidden .git directory containing the entire history: every commit, branch and tag. It can be local (only on your computer) or remote (cloned on GitHub). Deleting .git loses the history but keeps your files; deleting the files while keeping .git leaves history with nothing to show.

git add moves changed files into the staging area — your draft of the next snapshot — so you can review exactly what will be recorded. git commit writes the staged snapshot permanently with a message describing why the change happened. Two steps by design: stage deliberately, commit intentionally.

A branch is a movable pointer to a commit — creating one costs almost nothing. Use a branch for every unit of work (feature, fix, experiment): it keeps unfinished code out of main, lets you review changes in a pull request, and makes abandoning a bad idea as simple as deleting the branch.

It depends on where the change lives. Unstaged edits: git restore file. Staged but uncommitted: git restore --staged file. Committed but not pushed: git reset --soft to keep changes staged. Already pushed: git revert commit — it writes a new commit that undoes the old one instead of rewriting shared history. The undoing chapter covers each case with commands.

A conflict happens when two branches changed the same lines and Git cannot choose automatically. Your file gets marked up with <<<<<<<, ======= and >>>>>>> sections; you edit it down to the correct result, remove the markers, then git add and git commit. Conflicts are normal, small and entirely fixable — they are not an error state.

A pull request (PR) is GitHub's proposal to merge one branch into another. It shows the diff, runs checks, and lets teammates comment line by line before the code lands. It is the centre of modern collaboration: work on a branch, open a PR, review, approve, merge.

Write the subject in imperative mood, under about 50 characters: "Add email validation to signup". Explain why, not what, in the body when it is not obvious. Many teams use Conventional Commits (feat:, fix:, docs:) so tools can generate changelogs — the workflows chapter shows the format in practice.

Secrets (API keys, .env files), dependencies (node_modules), build output (dist), and operating-system junk (.DS_Store, Thumbs.db). A .gitignore file excludes them from the start; the common mistakes chapter shows what to do if something already slipped into history.