Chapter 1 — Getting Started
This is the first chapter of Git. Through the simplest possible workflow, we walk through one full cycle: **write the project skeleton → commit → run**.
What you'll learn
- 1Understand the basic structure of a Git project (`#include`, `main`, `printf`, `return`) — wait, that was for C. Here: `git init`, `git add`, `git commit`, `git status`, `git log`.
- 2Install and configure Git on your machine.
- 3Use `git config` to set up your name and email.
- 4Create your first repository and commit using just the terminal.
- 5Understand escape concepts like Working Directory / Staging / Repository.
Why Start with This?
Even before knowing every command, getting the **first cycle (write → stage → commit → log)** working end-to-end already proves that your environment (Git, PATH, encoding) is sane. That's worth more than memorizing syntax.
Core Concepts
1) Installing Git
Windows installers
| Tool | Installer | Description | Official download |
|---|---|---|---|
| Git for Windows | `Git-2.52.0-64-bit.exe` | Git CLI + Git Bash. Required to run git commands on Windows. | git-scm.com/install/windows |
| TortoiseGit | `TortoiseGit-2.18.0.1-64bit.msi` | GUI client that integrates Git into Windows Explorer. Lets you commit, view log, and diff with the mouse — handy if you're not yet comfortable with the command line. Install after Git for Windows. | tortoisegit.org/download |
Install order (Windows): Git for Windows first, then TortoiseGit. TortoiseGit uses Git for Windows as its backend, so Git must be installed first.
macOS / Linux
# macOS
brew install git
# Ubuntu / Debian
sudo apt update && sudo apt install gitVerify:
git --version
# git version 2.44.02) Global user setup
Every commit you make embeds the author. Set them once globally:
git config --global user.name "John Doe"
git config --global user.email "john@example.com"
# Check
git config --list --global| Scope | Applies to |
|---|---|
| `--global` | All your repositories |
| `--local` | The current repository only (`.git/config`) |
| `--system` | The whole machine |
3) Initializing a repository (`git init`)
mkdir my-project
cd my-project
git init
# Initialized empty Git repository in .../my-project/.git/Once a `.git/` folder exists, Git starts tracking this directory.
4) Your first commit
working directory → (git add) → staging area → (git commit) → repositoryecho "# My Project" > README.md
git add README.md
git commit -m "docs: add README"5) The three areas
| Area | What it holds |
|---|---|
| Working directory | The actual files on disk |
| Staging area | Changes queued for the next commit |
| Repository (`.git`) | The committed snapshots, kept permanently |
Examples
Example 1 — `ex01_setup.sh`: Verify Git version and current user config
#!/usr/bin/env bash
set -euo pipefail
echo "=== Git version check ==="
git --version
echo ""
echo "=== Current global user config ==="
git config --global user.name || echo "(user.name not set)"
git config --global user.email || echo "(user.email not set)"**Output**
=== Git version check ===
git version 2.44.0
=== Current global user config ===
John Doe
john@example.comKey: `git config --global` values can be queried any time.
Example 2 — `ex02_init.sh`: Initialize a temp repo and commit
#!/usr/bin/env bash
set -euo pipefail
REPO=$(mktemp -d)
echo "Working directory: $REPO"
cd "$REPO"
git init
git config user.name "Demo User"
git config user.email "demo@example.com"
echo "# Hello Git" > README.md
git add README.md
git commit -m "chore: initial commit"
echo ""
echo "=== Commit list ==="
git log --oneline**Output**
Working directory: /tmp/tmp.XyZ123
Initialized empty Git repository in /tmp/tmp.XyZ123/.git/
[main (root-commit) a1b2c3d] chore: initial commit
1 file changed, 1 insertion(+)
create mode 100644 README.md
=== Commit list ===
a1b2c3d chore: initial commitKey: `git init` → `git add` → `git commit` is the basic cycle.
Example 3 — `ex03_status.sh`: Observe the three areas
#!/usr/bin/env bash
set -euo pipefail
REPO=$(mktemp -d)
cd "$REPO"
git init -q
git config user.name "Demo User" && git config user.email "demo@example.com"
echo "file1" > a.txt
echo "[1] After adding file (status)"
git status
git add a.txt
echo ""
echo "[2] After git add (status)"
git status
git commit -q -m "add a.txt"
echo ""
echo "[3] After commit (status)"
git status**Output**
[1] After adding file (status)
On branch main
Untracked files:
a.txt
[2] After git add (status)
On branch main
Changes to be committed:
new file: a.txt
[3] After commit (status)
On branch main
nothing to commit, working tree cleanKey: `git status` tells you which of the three areas your file is in.
Example 4 — `ex04_inspect.sh`: Inspect commit history
#!/usr/bin/env bash
set -euo pipefail
REPO=$(mktemp -d)
cd "$REPO"
git init -q
git config user.name "Demo User" && git config user.email "demo@example.com"
echo "first content" > file.txt
git add file.txt && git commit -q -m "feat: first file"
echo "second line added" >> file.txt
git add file.txt && git commit -q -m "feat: add second line"
echo "=== git log --oneline ==="
git log --oneline
echo ""
echo "=== git show HEAD ==="
git show HEAD**Output**
=== git log --oneline ===
b2c3d4e feat: add second line
a1b2c3d feat: first file
=== git show HEAD ===
commit b2c3d4e...
Author: Demo User <demo@example.com>
Date: ...
feat: add second line
diff --git a/file.txt b/file.txt
...
+second line addedKey: `git log` shows commits in reverse order; `git show HEAD` shows the latest commit's diff.
Through a different lens
| Git concept | Everyday analogy |
|---|---|
| Repository | A photo album |
| Commit | A single photo |
| Staging area | Print-ready tray |
| `git add` | Putting a photo into the tray |
| `git commit` | Pasting the photo into the album |
Common mistakes
- **Committing without `git add`** — nothing is staged, you get "nothing to commit".
- **No user.name/email** — the commit fails with "Please tell me who you are".
- **Running `git init` in your home directory** — every file becomes tracked, `.git` grows huge.
- **Blank commit message** — without `-m`, the editor opens; saving with an empty message aborts the commit.
- **`--global` vs `--local` confusion** — on a work machine you might accidentally commit with a personal email.
Recap
- `git config --global user.name/email` sets the author.
- `git init` → `git add` → `git commit` is the basic cycle.
- `git status` shows the three-area state; `git log` shows commit history.
- `git show <commit>` displays the diff of a specific commit.
Try it
cd src
chmod +x ex01_*.sh ex02_*.sh ex03_*.sh ex04_*.sh
./ex01_setup.sh
./ex02_init.sh
./ex03_status.sh
./ex04_inspect.shStretch:
- Change your editor: `git config --global core.editor "vim"`.
- Try a graph view: `git log --oneline --graph --all`.
💻 Examples
Runnable examples — see the output yourself.
#!/usr/bin/env bash
set -euo pipefail
echo "=== Git version check ==="
git --version
echo ""
echo "=== Current global user config ==="
NAME=$(git config --global user.name 2>/dev/null || true)
EMAIL=$(git config --global user.email 2>/dev/null || true)
if [ -z "$NAME" ]; then
echo "user.name: (not set)"
else
echo "user.name: $NAME"
fi
if [ -z "$EMAIL" ]; then
echo "user.email: (not set)"
else
echo "user.email: $EMAIL"
fi
echo ""
echo "=== How to set ==="
echo " git config --global user.name \"John Doe\""
echo " git config --global user.email \"john@example.com\""
=== Git version check ===
git version 2.44.0
=== Current global user config ===
John Doe
john@example.com#!/usr/bin/env bash
set -euo pipefail
REPO=$(mktemp -d)
echo "Working directory: $REPO"
cd "$REPO"
git init -b main
git config user.name "Demo User"
git config user.email "demo@example.com"
git config commit.gpgsign false
echo "# Hello Git" > README.md
git add README.md
git commit -m "chore: initial commit"
echo ""
echo "=== Commit list ==="
git log --oneline
echo ""
echo "=== .git ==="
ls .git/
# cleanup
rm -rf "$REPO"
echo ""
echo " directory done"
Working directory: /tmp/tmp.XyZ123
Initialized empty Git repository in /tmp/tmp.XyZ123/.git/
[main (root-commit) a1b2c3d] chore: initial commit
1 file changed, 1 insertion(+)
create mode 100644 README.md
=== Commit list ===
a1b2c3d chore: initial commit#!/usr/bin/env bash
set -euo pipefail
REPO=$(mktemp -d)
cd "$REPO"
git init -q -b main
git config user.name "Demo User"
git config user.email "demo@example.com"
git config commit.gpgsign false
echo "file1" > a.txt
echo "[1] After adding file (status) (Untracked)"
git status
git add a.txt
echo ""
echo "[2] After git add (status) (Staged)"
git status
git commit -q -m "add a.txt"
echo ""
echo "[3] After commit (status) (Clean)"
git status
echo "edit content" >> a.txt
echo ""
echo "[4] file edit (after) status (Modified)"
git status
rm -rf "$REPO"
[1] After adding file (status)
On branch main
Untracked files:
a.txt
[2] After git add (status)
On branch main
Changes to be committed:
new file: a.txt
[3] After commit (status)
On branch main
nothing to commit, working tree clean#!/usr/bin/env bash
set -euo pipefail
REPO=$(mktemp -d)
cd "$REPO"
git init -q -b main
git config user.name "Demo User"
git config user.email "demo@example.com"
git config commit.gpgsign false
echo "First content" > file.txt
git add file.txt && git commit -q -m "feat: first file"
echo "Adding second line" >> file.txt
git add file.txt && git commit -q -m "feat: add second line"
echo "=== git log --oneline ==="
git log --oneline
echo ""
echo "=== git log --stat ==="
git log --stat --oneline
echo ""
echo "=== git show HEAD ==="
git show HEAD
echo ""
echo "=== git show HEAD~1 ( (before) commit) ==="
git show HEAD~1 --stat
rm -rf "$REPO"
=== git log --oneline ===
b2c3d4e feat: add second line
a1b2c3d feat: first file
=== git show HEAD ===
commit b2c3d4e...
Author: Demo User <demo@example.com>
Date: ...
feat: add second line
diff --git a/file.txt b/file.txt
...
+second line added📝 Exercises
Try them yourself first, then open the solution to compare.
Problem 1 (hw01.sh)
Goal: Set your own name and email as Git's global config, then verify the result.
- Filename: hw01.sh
# Expected output (your own name/email)
user.name=John Doe
user.email=john@example.com▶Toggle solution
#!/usr/bin/env bash
set -euo pipefail
# (before) user.name · user.email setup (after) check
git config --global user.name "John Doe"
git config --global user.email "john@example.com"
echo "=== (before) Git setup check ==="
git config --list --global | grep -E "^user\."
# Expected output (your own name/email)
user.name=John Doe
user.email=john@example.comProblem 2 (hw02.sh)
Goal: In a fresh temp directory, create a new Git repo, write a `README.md`, make the first commit, and inspect the log.
- Filename: hw02.sh
# Expected output
Initialized empty Git repository in /tmp/tmp.XXXXX/.git/
a1b2c3d docs: initial README▶Toggle solution
#!/usr/bin/env bash
set -euo pipefail
REPO=$(mktemp -d)
echo "repository : $REPO"
cd "$REPO"
git init -b main
git config user.name "John Doe"
git config user.email "john@example.com"
git config commit.gpgsign false
echo "# My first repository" > README.md
git add README.md
git commit -m "docs: initial README"
echo ""
echo "=== commit log ==="
git log --oneline
rm -rf "$REPO"
echo "cleanup done"
# Expected output
Initialized empty Git repository in /tmp/tmp.XXXXX/.git/
a1b2c3d docs: initial READMEAll lecture materials and example code are openly available on GitHub.
View on GitHub ↗