Skip to content

Beginner · Git in depth · topic 10 of 53 · 30 min

Git basics: repositories, staging and commits

Explanation

Git records snapshots of your project, called commits, so you can see who changed what, when and why, and go back at any time. Every change moves through three areas: the working directory (your files), the staging area (what goes into the next commit) and the repository (the saved history). A handful of commands, add, commit, status, log and diff, cover most of your daily work.

Why version control?

Without version control, teams email zip files or keep folders called final, final2 and final-really. Nobody knows which copy is current, and an old version is lost the moment someone saves over it. A version control system records every change to a set of files, with the author, the time and a message saying why. You can compare any two versions, find which change broke something, and undo it.

Git is the version control system almost every team uses today. It is distributed: every developer has a full copy of the whole history on their own laptop, not just the latest files. You can commit, view history and create branches with no network at all. A shared server such as GitHub, GitLab or Bitbucket is simply one more copy that everyone agrees to sync with.

Think of it like this: Think of a commit as a photo of your whole project, taken whenever you choose. The staging area is the group of people you arrange in front of the camera before you press the button. Only what you arrange gets into the photo, and the photo album (the repository) keeps every photo in order.

The three areas

AreaWhat it isHow a change gets there
Working directoryThe normal files you edit in your editorYou save a file
Staging area (index)A list of exactly what the next commit will containgit add file
Repository (.git folder)All commits, the full historygit commit

The staging area is what makes Git different from a simple backup. If you changed three files but only two belong to the bug fix, you stage those two and commit them with a clear message. The third change waits for its own commit. Small, focused commits are much easier to review and to undo.

First-time setup and a first repository

bash
git config --global user.name "Asha Rao"
git config --global user.email "asha@example.com"
git config --global init.defaultBranch main   # name of the first branch in new repos

mkdir shop-api && cd shop-api
git init                       # creates the hidden .git folder
echo "# Shop API" > README.md
git status                     # README.md is untracked
git add README.md              # stage it
git commit -m "Add README"     # save a snapshot
git log --oneline              # e.g. 3f9c2ab Add README
Your name and email are written into every commit you make. git clone <url> is the other way to start: it copies an existing repository with all its history.

Depending on your Git version, git init may call the first branch master. Setting init.defaultBranch to main gives new repositories the same name GitHub uses for new repositories.

Seeing what changed

bash
git status                   # which files are changed, staged or untracked
git diff                     # changes NOT yet staged (working directory vs staging area)
git diff --staged            # changes staged for the next commit (staging area vs last commit)
git log --oneline --graph    # short history, with a drawing of branches
git show 3f9c2ab             # one commit: author, date, message and its changes
git diff --cached is another name for git diff --staged.

What a commit really is

A commit stores four things: a snapshot of every tracked file, a pointer to its parent commit (the one before it), the author and time, and the message. Git computes a hash of all this, a long hexadecimal ID such as 3f9c2ab1e0d4... (40 characters with SHA-1, the default). You usually type only the first 7 characters. Because the parent is part of the hash, changing any old commit changes its ID and the ID of every commit after it. This is why history in Git is very hard to tamper with silently.

Good commit messages

  • A short subject line, about 50 characters, written as a command: "Fix GST rounding on invoices", not "fixed stuff".
  • If needed, a blank line and then a body explaining WHY the change was made, wrapped at about 72 characters.
  • One logical change per commit. "Add login page and upgrade database driver" should be two commits.

Ignoring files with .gitignore

Some files must never be committed: installed packages, build output, log files and secrets. List patterns for them in a file named .gitignore at the top of the repository, and git status stops showing them.

output
# Any file ending in .log, in any folder
*.log
# ...except keep.log (! means "do not ignore")
!keep.log
# A trailing slash matches a directory with this name, at any depth
node_modules/
# A leading slash anchors the pattern to the repository root only
/build
# Local secrets
.env
A # starts a comment only at the beginning of a line. Later lines win over earlier ones, which is why !keep.log comes after *.log.

Common mistakes and how to fix them

Careful: Committing a secret (an API key or .env file) is the classic mistake. Deleting it in the next commit is NOT enough: the old commit still contains it, and anyone with the repository can read it. Rotate the secret at once (make a new key and disable the old one), then clean history if needed. Prevent it by adding .env to .gitignore before your first commit.
  • Added a file to .gitignore but Git still tracks it? .gitignore only affects untracked files. Run git rm --cached file to stop tracking it, then commit.
  • Staged the wrong file? git restore --staged file takes it out of the staging area and keeps your edits.
  • Want to throw away edits to a file? git restore file puts back the last committed version. Careful: those edits are gone.
  • Wrong message on the last commit (not pushed yet)? git commit --amend -m "Better message".
Tip: Run git status before every add and every commit. It costs a second and shows you exactly what is about to happen.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Git basics: repositories, staging and commits · 1/8

Git basics

Git keeps a history of your project as a series of snapshots called commits. You can always see who changed what, and go back.

Prefer a video by a teacher? Find free videos on “git tutorial for beginners staging area commit” on YouTube ↗

In real life: A college project team in Pune

Four final-year students build an attendance app. Before Git, they shared code on a pen drive and twice lost a whole day of work when someone copied an old folder over a new one. Now each student commits small changes with clear messages and pushes to a shared GitHub repository. When the QR scanning broke two days before the demo, git log showed which commit changed the scanner, and git show displayed exactly the three lines that caused it.

bash
git log --oneline --graph
* 9b1e4d2 Fix QR scanner timeout on old phones
* 51ac0f7 Add monthly attendance report
* 0c3d9e8 Add QR scanner screen
* 3f9c2ab Add README
Each line is one commit: its short ID and subject.

Practice (0/3 done)

Task 1 · Question

You edited app.py and want it in the next commit. Which command moves it to the staging area?

Task 2 · Code · Python

Write matches(path, pattern) for three simple .gitignore pattern kinds. path is a file path with "/" between folders, like "logs/error.log". 1. A pattern ending in "/" (like "node_modules/") matches if any FOLDER in the path has that name. 2. A pattern starting with "/" (like "/build") matches only if the FIRST part of the path has that name. 3. Any other pattern (like "*.log" or ".env") matches if ANY part of the path matches it, where * stands for any characters. Tip: fnmatchcase(name, pattern) from the fnmatch module checks one name against a pattern with *.

Task 3 · Code · Python

Now write is_ignored(path, rules) using a list of .gitignore lines. Skip blank lines and lines starting with "#". Go through the rules in order. A rule starting with "!" is a negation: if the rest of it matches, the file is NOT ignored. Any other rule that matches makes the file ignored. The LAST matching rule decides. If no rule matches, the file is not ignored. The matches(path, pattern) function from the previous task is given.

Quick quiz

Question 1

1.What does "Git is distributed" mean?

Question 2

2.You ran git add on a file. Which command shows the changes that will go into the next commit?

Question 3

3.Which of these is NOT stored in a commit?

Question 4

4.You added config.json to .gitignore, but git status still shows changes to it. Why?

Question 5

5.Which is the best commit subject line?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What does "Git is distributed" mean?

Answer: Every clone has the full history, so most work needs no network

Every clone holds the whole history. Commits, logs and branches work offline; the server is just a shared copy.

You ran git add on a file. Which command shows the changes that will go into the next commit?

Answer: git diff --staged

git diff --staged compares the staging area with the last commit. Plain git diff shows only unstaged changes.

Which of these is NOT stored in a commit?

Answer: The list of files in .gitignore that were skipped

A commit stores a snapshot, its parent(s), author, committer and message. Ignored files are simply never part of it.

You added config.json to .gitignore, but git status still shows changes to it. Why?

Answer: .gitignore does not affect files Git already tracks

.gitignore only stops untracked files from being added. Run git rm --cached config.json and commit to stop tracking it.

Which is the best commit subject line?

Answer: Fix rounding of GST on invoice totals

A good subject is short, specific and written as a command describing one change.

Which commit message is best?Related

Answer: Fix PIN code check for codes starting with 0

A good subject says what the commit does, as a short command, so the history explains itself.

From Git and GitHub

What is a Git branch for?Related

Answer: Working on a feature separately without breaking the main code

A branch is a separate line of work that you can merge back into main when it is ready.

From Setting up your tools

Which file should you add to .gitignore?Related

Answer: .env

.env holds real secrets, so it must never go into Git. .env.example has no secrets and is meant to be shared.

From Environment variables and config

main has no new commits since feature was created. What does git merge feature (run on main) do by default?Related

Answer: Moves main forward to the tip of feature (fast-forward)

When main is an ancestor of feature, Git just moves the pointer. Use --no-ff if you want a merge commit anyway.

From Branching, merging and conflicts

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 4 more topics in “Git in depth” before its exam: Branching, merging and conflicts, Rebase, undo and rescue: rebase, reset, revert, reflog and stash, Collaboration: remotes, pull requests and branching strategies, Semantic versioning, tags and releases.
  2. Module 3 exam: Git in depth · 13 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Docker. 53 topics left in the course before the final exam.

← Previous: Linux networking for DevOps