Before this lesson
Understand local commits and branches. The remote exercise uses local directories only.
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
Simulate collaboration with two local copies and understand upstream branches.
Understand the mechanism
A remote is a named address configuration; origin is conventional, not special. origin/main records the last known remote position. fetch refreshes that information without directly merging changes into the current branch.
push transfers commits and requests remote reference updates. -u sets upstream tracking. pull combines fetching and integration, whose strategy should be explicit. This example fetches, inspects and then merges with --ff-only.
A local bare repository plays the server without accounts, networking or public publication. Real hosting uses SSH or HTTPS authentication; keep tokens out of remote URLs and committed files. A GitHub pull request is a hosting review workflow, not a core Git command.
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 init --bare -b main "$lab/remote.git"
git remote add origin "$lab/remote.git"
git push -u origin main
git clone "$lab/remote.git" "$lab/teammate"
git -C "$lab/teammate" config user.name "Practice Teammate"
git -C "$lab/teammate" config user.email 'teammate'@'example.invalid'
git -C "$lab/teammate" config commit.gpgsign false
printf 'Team review\n' >> "$lab/teammate/notes.txt"
git -C "$lab/teammate" add notes.txt
git -C "$lab/teammate" commit -m "Add team review"
git -C "$lab/teammate" push origin main
git fetch origin
git log --oneline HEAD..origin/main
git merge --ff-only origin/main
cat notes.txt
Trace and verify
After fetch, local main has not moved and HEAD..origin/main shows Add team review. Fast-forward integration adds Team review to notes.txt. Both copies and the bare repository remain under the practice directory.
Common mistakes and boundaries
A rejected push may indicate unintegrated commits, permissions or branch protection. Diagnose it first; force-pushing is not a general repair.
Practice challenge
Append, commit and push from the original copy, then fetch and fast-forward the teammate copy.
Reference solution and reasoning
Repeat fetch and merge --ff-only in reverse. Both HEAD identifiers should match. If history diverges, --ff-only refuses until an integration strategy is chosen.