devops-roadmap
stage 05 / 16
Beginner4 lessons · ~4 min read · 2 weeks to practise

Git & version control

The system of record for code and, soon, infrastructure

Git is the backbone of CI/CD and GitOps. Master the model, the collaboration workflow, the rescue commands, and how versions and releases are automated.

0/4 read
On this page · 4 lessons
05.01

Git fundamentals

The three areas, commits as snapshots, branches as pointers, merge vs rebase, and recovering from mistakes.

Git is the system of record for everything you do — code, pipelines, and soon infrastructure itself. Understanding its model, not just memorising commands, is what stops the panic.

Git has three areas: your working directory (files you edit), the staging area (changes you've marked with git add), and the repository (permanent snapshots created by git commit). A commit is an immutable snapshot with a parent, which is how history forms a chain.

The daily loop:

git status              # what changed?
git add file.py         # stage it
git commit -m "message" # snapshot it
git push                # send to the remote

Branches are just cheap, movable pointers to a commit — creating one is instant. You merge to combine histories (keeps both lines) or rebase to replay your commits on top of another branch (keeps history linear). When two people change the same lines, you get a conflict; Git marks it and you choose the result.

The confidence booster: almost nothing is truly lost. git reflog remembers where you were, so you can recover from most mistakes.

05.02

Collaboration & branching strategies

Pull requests and review, trunk-based vs GitFlow, branch protection, and conventional commits.

Git alone is version control; workflows are how a team uses it without stepping on each other. This is where GitHub and GitLab come in.

The unit of collaboration is the Pull Request (PR) / Merge Request: you push a branch, open a PR, and teammates review the diff before it merges. Good PRs are small, have a clear description, and pass automated checks (tests, linting) before a human even looks.

Two dominant branching strategies:

  • Trunk-based development: everyone merges tiny changes into main frequently, behind feature flags if needed. Favoured by high-performing teams because it minimises painful merges.
  • GitFlow: long-lived develop, release, and feature branches. More ceremony; better suited to versioned software with scheduled releases.

Protect main with branch protection rules: require reviews and green CI before merge, and forbid force-pushes. Adopt Conventional Commits (feat:, fix:, chore:) so history is readable and changelogs can be generated automatically.

05.03

Advanced Git: rebase, cherry-pick, bisect, reflog

Curate history, hotfix a single commit, binary-search for the bug, and undo almost any disaster.

Once the basics are automatic, a handful of advanced Git commands make you the person who rescues the repository.

  • git rebase -i HEAD~5 — interactive rebase. Squash messy work-in-progress commits into one clean commit, reword messages, drop mistakes. Clean history is a gift to reviewers. Rule: rebase your own unpushed branch, never shared history.
  • git cherry-pick <sha> — copy one specific commit onto another branch. The standard way to hotfix production without shipping everything else on main.
  • git bisect — binary-search your history for the commit that introduced a bug. Mark a known-good and known-bad commit, and Git walks you through the middle each time. It finds the culprit in ~log₂(n) steps — magic on a big repo.
  • git stash — park uncommitted changes to switch context fast.
  • git reflog — the safety net. It records every position HEAD has been at, so even a "lost" commit after a bad reset is recoverable. Almost nothing in Git is truly gone.
  • Hooks (.git/hooks, or pre-commit framework) run checks automatically — lint, format, secret-scan — before a bad commit ever exists.
05.04

SemVer, tags & automated releases

MAJOR.MINOR.PATCH as a contract, immutable tags, changelogs — and why you never deploy `latest`.

"Which version is in production?" must have a precise answer. That's what versioning and release management give you.

Semantic Versioning (SemVer) is the standard: MAJOR.MINOR.PATCH.

  • PATCH (1.4.2 → 1.4.3) — backwards-compatible bug fix.
  • MINOR (1.4.2 → 1.5.0) — new functionality, still backwards-compatible.
  • MAJOR (1.4.2 → 2.0.0) — a breaking change. Consumers must act.

That contract lets other teams upgrade safely, and it lets tools auto-update patches without fear.

In Git, a release is a tag (git tag -a v1.5.0 -m "..."), an immutable pointer to a commit. Your CI builds artifacts from tags, so a version maps to exactly one build.

Automate it: with Conventional Commits (feat:, fix:, feat!: for breaking), tools like semantic-release read your commit messages, work out the next version, tag it, generate a CHANGELOG, and publish — no human deciding version numbers.

Never deploy latest. A container tagged latest is unreproducible and unrollbackable; deploy app:1.5.0 and you always know exactly what's running and what to roll back to.

practise — build these
  • $Contribute a fix to an open-source project end-to-end: fork, branch, PR, address review, merge.
  • $Set up a repo with branch protection, required checks, conventional commits, and automated SemVer releases.