← Back to Git series
🔀
Git & GitHub Deep Dive
Git install · user config · git init · first commit

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**.

installconfiginitcommit
Duration
1-2 hours
Level
📊 Beginner
Prerequisite
🎯 None
Outcome
Install Git and make your first repo & commit

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

ToolInstallerDescriptionOfficial 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

bash
# macOS
brew install git

# Ubuntu / Debian
sudo apt update && sudo apt install git

Verify:

bash
git --version
# git version 2.44.0

2) Global user setup

Every commit you make embeds the author. Set them once globally:

bash
git config --global user.name  "John Doe"
git config --global user.email "john@example.com"

# Check
git config --list --global
ScopeApplies to
`--global`All your repositories
`--local`The current repository only (`.git/config`)
`--system`The whole machine

3) Initializing a repository (`git init`)

bash
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

text
working directory → (git add) → staging area → (git commit) → repository
bash
echo "# My Project" > README.md
git add README.md
git commit -m "docs: add README"

5) The three areas

AreaWhat it holds
Working directoryThe actual files on disk
Staging areaChanges 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

bash
#!/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**

text
=== Git version check ===
git version 2.44.0

=== Current global user config ===
John Doe
john@example.com

Key: `git config --global` values can be queried any time.

Example 2 — `ex02_init.sh`: Initialize a temp repo and commit

bash
#!/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**

text
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

Key: `git init` → `git add` → `git commit` is the basic cycle.

Example 3 — `ex03_status.sh`: Observe the three areas

bash
#!/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**

text
[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

Key: `git status` tells you which of the three areas your file is in.

Example 4 — `ex04_inspect.sh`: Inspect commit history

bash
#!/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**

text
=== 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

Key: `git log` shows commits in reverse order; `git show HEAD` shows the latest commit's diff.

Through a different lens

Git conceptEveryday analogy
RepositoryA photo album
CommitA single photo
Staging areaPrint-ready tray
`git add`Putting a photo into the tray
`git commit`Pasting the photo into the album

Common mistakes

  1. **Committing without `git add`** — nothing is staged, you get "nothing to commit".
  2. **No user.name/email** — the commit fails with "Please tell me who you are".
  3. **Running `git init` in your home directory** — every file becomes tracked, `.git` grows huge.
  4. **Blank commit message** — without `-m`, the editor opens; saving with an empty message aborts the commit.
  5. **`--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

bash
cd src
chmod +x ex01_*.sh ex02_*.sh ex03_*.sh ex04_*.sh
./ex01_setup.sh
./ex02_init.sh
./ex03_status.sh
./ex04_inspect.sh

Stretch:

  1. Change your editor: `git config --global core.editor "vim"`.
  2. Try a graph view: `git log --oneline --graph --all`.

💻 Examples

Runnable examples — see the output yourself.

ex01_setup.shVerify Git version and current user config
CODE
#!/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\""
▶ Output
=== Git version check ===
git version 2.44.0

=== Current global user config ===
John Doe
john@example.com
ex02_init.shInitialize a temp repo and commit
CODE
#!/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"
▶ 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 commit
ex03_status.shObserve the three areas
CODE
#!/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"
▶ 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 clean
ex04_inspect.shInspect commit history
CODE
#!/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"
▶ 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 added

📝 Exercises

Try them yourself first, then open the solution to compare.

Exercise 1

Problem 1 (hw01.sh)

Goal: Set your own name and email as Git's global config, then verify the result.

Requirements
  • Filename: hw01.sh
Sample I/O
# Expected output (your own name/email)
user.name=John Doe
user.email=john@example.com
Toggle solution
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\."
▶ Output
# Expected output (your own name/email)
user.name=John Doe
user.email=john@example.com
Exercise 2

Problem 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.

Requirements
  • Filename: hw02.sh
Sample I/O
# Expected output
Initialized empty Git repository in /tmp/tmp.XXXXX/.git/
a1b2c3d docs: initial README
Toggle solution
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"
▶ Output
# Expected output
Initialized empty Git repository in /tmp/tmp.XXXXX/.git/
a1b2c3d docs: initial README
Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub ↗