Week 1: Git Fundamentals & Your First Repo

This course assumes nothing about your prior version-control experience — just that you can open a terminal. This week installs Git, configures your identity, and builds a mental model of the three places a change lives in Git before it's committed: the working directory, the staging area, and the commit history.

Module 1 of 5 Week 1 of 5 ~2–3 Hours Hands-on Exercise Included

By the end of this week, you'll be able to

  • Install Git and configure your name, email & default editor
  • Explain the working directory → staging area → commit flow
  • Inspect history with log and diff, and keep noise out with .gitignore

1. What Git Is & Installing It

Git is a distributed version control system: it takes snapshots of a project's files over time, and every clone of a repository carries the entire history, not just the latest version. That's the key difference from older centralized systems — you can commit, branch and view history completely offline, and there's no single point of failure holding the only copy of the project.

terminal
# macOS (Homebrew)
brew install git

# Ubuntu/Debian
sudo apt install git

# Windows -- install via https://git-scm.com/download/win
# (this also installs Git Bash, a Unix-style shell for Windows)

git --version
# git version 2.4x.x

A repository ("repo") is a project folder Git is tracking — it stores its entire history inside a hidden .git subfolder. Nothing about a repo requires the internet or a hosting service: Git itself is just the tool that runs on your machine. GitHub, which this course gets to in Week 3, is a separate product that hosts repos and adds collaboration features on top.

2. Configuring Git & Your First Repo

Before your first commit, tell Git who you are — every commit is permanently stamped with this identity:

terminal
git config --global user.name "Ada Lovelace"
git config --global user.email "ada@example.com"
git config --global init.defaultBranch main
git config --global core.editor "code --wait"   # optional: use VS Code for commit messages

# Confirm it stuck:
git config --list

--global applies the setting to every repo on your machine, stored in ~/.gitconfig. Drop it to set a value for just the current repo instead.

Now create a repo and make your first commit:

terminal
mkdir hello-git && cd hello-git
git init
# Initialized empty Git repository in .../hello-git/.git/

echo "# Hello Git" > README.md
git add README.md
git commit -m "Initial commit"
# [main (root-commit) 3f9a1c2] Initial commit
#  1 file changed, 1 insertion(+)
#  create mode 100644 README.md
Write commit messages in the imperative mood

"Add login form", not "Added login form" or "Adds login form". This matches the convention Git itself uses for auto-generated messages (e.g. "Merge branch 'x'"), and it's what every team style guide asks for once you're collaborating.

3. The Three Trees: Working Directory, Staging Area & Commits

Every file in a Git repo can exist in up to three places at once, and almost every confusing Git moment traces back to not knowing which one you're looking at:

  1. Working directory — the actual files on disk, exactly as you see them in your editor.
  2. Staging area (the "index") — a draft of what your next commit will contain. git add copies changes here.
  3. Commit history — permanent, named snapshots. git commit takes whatever's staged and seals it into history.
terminal
echo "console.log('hi');" > app.js
git status
#   Untracked files: app.js

git add app.js
git status
#   Changes to be committed: new file: app.js

git commit -m "Add app.js"
git status
#   nothing to commit, working tree clean

git add is not "share this file" — it's "include this exact version of this file in my next commit." Edit the file again after staging it, and you now have two different versions of it in play: the staged one and the newer working-directory one, until you git add again.

terminal
# Common shortcuts:
git add .              # stage everything changed/new in the current folder
git add -A             # stage everything changed/new/deleted, repo-wide
git add -p             # interactively choose which hunks to stage
git commit -am "msg"   # stage all tracked-file changes AND commit, in one step
git add -p is worth the habit

It lets you review and stage a file change by change instead of all-or-nothing — the single best tool for keeping commits small and focused on one logical change each.

4. Viewing History: log, diff & status

git log walks the commit history, newest first:

terminal
git log
# commit 3f9a1c2... (HEAD -> main)
# Author: Ada Lovelace <ada@example.com>
# Date:   Mon Aug 17 10:02:11 2026
#     Add app.js

git log --oneline --graph          # compact, one line per commit
git log -p -- app.js               # full diff for every commit touching app.js
git log --author="Ada"             # filter by author

git diff shows what's changed but not yet staged; git diff --staged shows what's staged but not yet committed:

terminal
echo "console.log('bye');" >> app.js
git diff
# -console.log('hi');
# +console.log('hi');
# +console.log('bye');

git add app.js
git diff             # empty -- nothing unstaged left
git diff --staged    # shows the staged addition instead

git status is the command you'll run more than any other — it always tells you exactly what's staged, what's modified, and what's untracked, in plain language. When in doubt, run it.

5. Ignoring Files with .gitignore

Not everything belongs in version control: build output, dependency folders, editor settings and secrets should never be committed. A .gitignore file at the repo root tells Git which paths to leave untracked entirely:

.gitignore
# Dependencies
node_modules/
vendor/

# Build output
dist/
build/
*.log

# Editor / OS
.vscode/
.DS_Store

# Secrets -- never commit these
.env
*.pem
.gitignore only works on untracked files

If a file was already committed before you added it to .gitignore, Git keeps tracking it. Remove it from tracking (but keep it on disk) with git rm --cached path/to/file, then commit that removal.

6. Hands-on Exercise

Hands-on

Track a small project from scratch

Build the habit of small, well-described commits before anything else in this course.

Requirements:

  1. Run git config to set your name and email, if you haven't already.
  2. Create a folder, run git init, and add a .gitignore that excludes at least *.log and node_modules/.
  3. Create three files (e.g. index.html, style.css, notes.log) and confirm with git status that notes.log is ignored, not just untracked.
  4. Stage and commit the other two files in two separate commits, each with an imperative-mood message.
  5. Edit one file, use git diff to review the change, then stage and commit it as a third commit.
  6. Run git log --oneline --graph and confirm you see all three commits.
Hint

If a file shows up in git status as untracked even though it matches your .gitignore pattern, double check the pattern is at the repo root and doesn't have a stray leading / or typo — .gitignore patterns are easy to get subtly wrong on the first try.

7. Knowledge Check

Four quick questions. Expand each to check your answer.

Q1

What's the difference between the working directory and the staging area?

The working directory is the actual files on disk as you're editing them. The staging area is a separate draft of exactly what will go into your next commit — git add copies a snapshot of a file into staging, and further edits in the working directory don't affect what's staged until you git add again.

Q2

Why is Git called "distributed" version control?

Every clone of a repository contains the full project history, not just the latest snapshot. That means committing, branching, and browsing history all work completely offline — there's no single central server required for those operations, unlike older centralized version control systems.

Q3

Why does git diff show nothing right after you run git add on a file?

git diff (no flags) only compares the working directory against the staging area. Once a file is fully staged, there's no difference between those two, so it shows nothing. The staged change itself is visible with git diff --staged, which compares staging against the last commit instead.

Q4

You added a file to .gitignore, but git status still shows it as modified. Why?

.gitignore only stops untracked files from being picked up. If the file was already committed before it was added to .gitignore, Git keeps tracking it regardless of the pattern. Fix it with git rm --cached <file> to stop tracking it (while leaving it on disk), then commit that change.