Before this lesson

Be able to read commit logs and create commits.

Use Git 2.35+ and a Bash-compatible terminal, such as Git Bash on Windows. Each complete example creates an independent temporary directory. Run it only in that practice repository. Configuration is repository-local and uses a practice identity. Temporary directories are not automatically removed; clean them up after finishing.

What you will be able to do

Develop on a branch and distinguish fast-forward from merge commits.

Understand the mechanism

A branch is a movable reference to a commit, not a copied project folder. switch changes the branch and relevant working files. Inspect uncommitted changes first; Git may refuse a switch that would overwrite them.

A destination can fast-forward when it is an ancestor of the source. --ff-only requires that situation. If both sides have new commits, merge or an agreed history-replay approach is needed.

This example deliberately creates a merge commit to preserve the feature boundary in the graph. Teams choose fast-forward or merge commits according to their history needs; neither is universally mandatory.

Runnable example

lab=$(mktemp -d)
cd "$lab"
git init -b main .
git config user.name "Honeysuck Learner"
git config user.email 'learner'@'example.invalid'
git config commit.gpgsign false
git config core.autocrlf false
printf 'Start learning\n' > notes.txt
git add notes.txt
git commit -m "Start learning notes"
git switch -c feature/checklist
printf 'Review before commit\n' > checklist.txt
git add checklist.txt
git commit -m "Add review checklist"
git switch main
git merge --no-ff feature/checklist -m "Merge review checklist"
git log --graph --oneline --all
git rev-list --parents -n 1 HEAD
git branch --merged

Trace and verify

main ends with checklist.txt and a tip with two parents. The graph shows the feature commit and merge node, and both branches are listed as merged.

Common mistakes and boundaries

A merge updates the current branch. Check git branch --show-current. Merging main while on feature does not deliver the feature into main.

Practice challenge

In a fresh run, use git merge --ff-only feature/checklist and compare commit counts.

Reference solution and reasoning

The original has 3 commits; fast-forward has 2, with main moving directly to the feature commit. Final files match despite the different graph.

Further reading