Module 1 · Foundations that hold everything up

Lesson 06 — Professional Git

Branches, rebase, conflicts and team workflows: the trade's collaboration tool.

Published
In this lesson
  1. Exercise 1 — Commits with intention
  2. Exercise 2 — Interactive rebase
  3. Exercise 3 — Simulated conflict
  4. Exercise 4 — Reflog
  5. Exercise 5 — Automatic bisect
  6. Exercise 6 — GitHub Flow
  7. Professor's summary

Mechanics are learned by breaking things. If any exercise didn't "fail" the way you expected, redo it reading every Git message: it is almost always explaining the answer to you.


Exercise 1 — Commits with intention

  1. Two commits, each with a type and a purpose: fix: correct error message (the typo hunk) and feat: add function X (the new hunk). With stuck-together hunks, e (edit) lets you delete from the hunk what doesn't belong to that commit and s (split) divides large hunks.
  2. With git add. and one "update" commit: history says "app.py changed" — neither what nor why. Operational consequences: reverting that commit also undoes the fix (or the feature), bisect cannot tell which one introduced a bug, and the reviewer reads two mixed topics (90% of giant PRs are born this way).

Exercise 2 — Interactive rebase

  1. A single feat: add counters to a.txt commit with the final content. The three old hashes cease to exist: rebase rewrites commits (new hashes, same author date).
  2. It is safe here because nobody else has those commits (your local branch, just created). It is dangerous on shared branches because clones holding the old hashes clash with the new history: every teammate would see "duplicates" on pull. The law: rebase your own unpublished work; never the published one.

Exercise 3 — Simulated conflict

  1. Git says CONFLICT (content): Merge conflict in README.md and leaves the merge paused (MERGE_HEAD exists). The file shows both blocks with markers.
  2. After resolving, add and commit, git log --graph shows the branch point with a merge commit joining the two lines: history is faithful to what happened (two parallel efforts, one integration point).
  3. With rebase, the final graph is linear: your commit is "rewritten" on top of main, as if you had started later. Essential difference: merge preserves the real branching; rebase rewrites to tell a linear story. For this course's PRs: rebase your branch to update it; squash-merge when integrating (linear main AND each change as one unit).

Exercise 4 — Reflog

  1. The commit no longer appears in git log and the working tree went back to the previous state.
  2. git reflog shows the reset: moving to HEAD~1 entry and, below it, the original commit:. git reset --hard HEAD@{1} (or the hash) recovers it with all its content. Nothing is truly deleted for ~90 days.
  3. Reflog: to recover your local work (accidental resets, rebases). Revert: to undo a commit already shared — it creates a new inverse commit without rewriting history (safe on main). Rule: local and unpublished → reflog/reset; published → revert.

Exercise 5 — Automatic bisect

  1. Git checks out the middle commit, test.sh runs, and in ~2-3 steps it points at the exact commit that created bug.txt. Final output: <hash> is the first bad commit.
  2. With 5 commits: 2-3 automatic tests (rounded log2(5)). By hand, worst case, 4 (and with 300 commits: 9 vs 300). The real value: bisect run with your tests turns "it broke last week" into a named, authored culprit commit in under a minute.

Exercise 6 — GitHub Flow

2-3. The conventional commit with the body explaining why; the PR with context and checklist; the honest self-review (e.g. "this uptime would be better read from /proc/uptime than from process time" and "the endpoint lacks a test") is exactly what you will ask of a teammate: practicing solo builds the habit.

  1. With squash, main shows a single feat(health): detail endpoint... (#N) commit — main's history becomes a list of intentions, not drafts. Deleting the branch avoids the cemetery of old feat/... branches.

Professor's summary

  • The commit is the unit of intention: type + why; add -p so history tells steps, not noise.
  • Rebase your own unpublished work; merge/squash when integrating; never rewrite other people's history.
  • Conflicts: a 4-step mechanic; prevented with short branches and small PRs.
  • Reflog rescues your local work; revert undoes the shared; (automated) bisect finds the culprit.
  • GitHub Flow: deployable main, small PR, green CI, squash, revert as the first answer to breakage.

With this you close the entire Module 1 (01-06): protocol, networking, concurrency, algorithms, the system and the team tool. When you submit these exercises we correct them, update your scoreboard and open Module 2 — Databases with Lesson 07 — Advanced SQL on PostgreSQL.