CAMPUX Cloud Bootcamp Phase Three · Class Eighteen
Phase Three — DevOps Core
Reading 40 min · Drills 6 · 3 Labs
Aligned to AZ-400
Class Eighteen

Repositories & collaboration

Git makes a solo engineer safe; GitHub is where a team of them becomes trustworthy — and the pull request, the review, and the rules on main are the machinery that turns individual commits into work an employer can rely on.

§1

The pull request is the unit of work

Last class you learned Git as a private tool — a ledger you commit to alone. GitHub is where that ledger goes to live with other people, and the moment more than one person can push to the same branch, "just commit it" stops being safe. The profession solved this with a single ritual, and almost everything you do as a cloud engineer from now on passes through it: the pull request. A PR is not a Git feature — Git has no idea it exists. It is a proposal, hosted by GitHub, that says: here is a branch, here is exactly how it differs from main, please look before it goes in.1

Pull request
A hosted proposal to merge one branch into another, carrying the diff, a description, the discussion, the reviews, and the automated checks. Nothing reaches the protected branch except through it, and its history survives long after the branch is deleted.

Think about what the PR actually is, because interviewers do. It is the smallest complete unit of professional change: a self-contained slice of work, described in prose, reviewed by a human, verified by machines, and recorded permanently. When you say in an interview that you "shipped a feature," what you mean — what they are checking you mean — is that you opened a PR, defended it in review, passed the checks, and merged it. The commit is the raw material; the pull request is the finished, accountable thing. A team that works this way can let six people change the same repository on the same afternoon without fear, because no change lands unseen. That discipline, not any command, is what "collaboration" names.

§2

What to say in a review

A review is the human half of the PR, and it is where junior engineers most often reveal themselves — not by missing bugs, but by not knowing how to talk. A good review is not a gate you slam or a rubber stamp you apply; it is a conversation with a clear purpose: get the change to a state you would both defend, without either person losing an afternoon or their dignity. There is a craft to it, and it is learnable.

Review the change, not the person
"This function reads confusingly" is fixable; "you write confusing code" is an insult with no next step. Address the diff, never the author.
Ask, don't decree
"What happens if this list is empty?" invites the author to see it themselves and leaves room for a reason you missed. It ages far better than "this is wrong."
Separate must-fix from nice-to-have
Label blocking concerns clearly and mark the rest as optional (many teams prefix them "nit:"). A wall of equal-weight comments hides the one that matters.
Approve when it is good enough
The goal is a change safe to ship, not a perfect one. Withholding approval over taste is how review becomes the thing everyone dreads.

The reviewer's job and the author's job are the same job seen from two sides: protect the codebase and respect the human. As the author, you make that easier — keep the PR small, write a description that says why and not just what, and reply to every comment even if only to say you have handled it. A 900-line pull request does not get reviewed; it gets skimmed and approved, which is worse than no review because it launders a false sense of safety. The reviewers who get promoted are the ones people are glad to be reviewed by, and that reputation is built one considerate comment at a time.

Review the change, not the person.

§3

The rules that make Fridays safe

Etiquette asks people to behave; branch protection makes the platform enforce it, so that good behaviour is not optional and not dependent on anyone remembering. Last class's disaster — a junior force-pushing over main and erasing a colleague's morning — is not fixed by a stern word. It is fixed by a rule that makes the force-push physically impossible. Branch protection (and its newer successor, rulesets) is a set of conditions GitHub attaches to a branch and refuses to let any push or merge violate.2

Table 1 — Protection rules worth knowing by name
RuleWhat it forces
Require a pull request before mergingNothing lands on the branch by direct push — every change arrives as a reviewable PR
Require approvalsThe PR needs a set number of approving reviews (one, for most teams) before it can merge
Dismiss stale approvalsNew commits after an approval reset it, so nobody sneaks changes in after the review
Require status checks to passNamed checks — build, tests, lint — must be green before the merge button will let you through
Require branches up to dateThe PR must be rebased or merged onto the latest main before merging, so checks run against what actually ships
Block force pushes & deletionsThe exact foot-gun from Class Seventeen — the platform simply refuses it

The reason this matters to your career is that it converts a promise into a property. "We always review before merging" is a hope; a required-approvals rule is a fact the repository will not bend. Notice the sharpest option, do not allow bypassing: without it, admins can override the rules, which quietly means the rules are advice. A team that protects main properly can deploy on a Friday afternoon, because the thing that would ruin the weekend cannot happen — not because everyone is being careful, but because the platform is.3

§4

CODEOWNERS — who must say yes

"Require one approval" is blunt: any teammate's approval counts, even on code they have never touched. Real teams need something sharper — a rule that says changes to the networking Bicep must be approved by whoever owns networking. That is the CODEOWNERS file: a plain text map from paths in the repository to the people or teams responsible for them.

# .github/CODEOWNERS — paths map to owners
*                       @campux/platform
/infra/network/         @campux/networking
*.bicep                 @campux/platform
/.github/workflows/     @campux/devops-leads

The syntax is gitignore-style patterns, each followed by one or more @user or @org/team owners; the last matching pattern wins, so order from general to specific. GitHub looks for the file in .github/, then the repository root, then docs/, and uses the first it finds. Two facts trip people up and both are worth memorising:

Owners need write access
An owner listed in the file must have explicit write permission on the repository, or GitHub silently ignores them as a valid reviewer.
It only bites when required
By itself, CODEOWNERS merely auto-requests reviews. It becomes mandatory only when the branch rule Require review from Code Owners is switched on — otherwise it is a polite suggestion.

Put the two together and you have expertise routed automatically: the person who understands a piece of the system is pulled into every change that touches it, without anyone having to remember to ask. On a small team CODEOWNERS may just formalise "the two of us"; on a large one it is the difference between review that finds real problems and review by whoever happened to be online. Either way, it encodes responsibility as configuration — exactly the move a cloud engineer is paid to make.

§5

A README that answers the interviewer

The README is the first file a stranger opens and, in an interview, the first artefact of yours they judge. Most are useless — a title, an install line, nothing about why the thing exists or how a newcomer starts. A good README is not documentation for its own sake; it is you, answering the reviewer's questions before they ask, in the order they ask them.

What and why
One paragraph: what this repository does and the problem it solves. A reader should know in fifteen seconds whether they are in the right place.
How to run it
The exact commands to get from clone to working, with prerequisites named. If a newcomer cannot start in five minutes, the README failed.
How it is structured
A short map of the important directories, so a reader knows where to look before they go looking.
How to contribute
Branch naming, the PR flow, what the checks expect. This is where you show you work like a professional, not a hobbyist.

Interviewers read READMEs because they cannot watch you work, so the README is the closest thing to a demonstration of how you think. A repository whose README explains its purpose, its setup, and its contribution rules tells them you understand that code is read far more than it is written — and that you write for the next person, who might be you in six months with no memory of today. The portfolio you build across Phase Three lives or dies on this file; Class Thirty-Six returns to it as the first five minutes of your interview. Write it as if it is.

Case File · Campux Retail

Locking down main

campux-platform grows a spine

The campux-platform repository from last class now holds work worth protecting, so you turn main from an open field into a guarded one. Three rules go on: require a pull request before merging, require one approving review, and block force pushes and deletions. A status check is wired in — the Bicep must validate — and marked required, so nothing merges until it is green. The junior who force-pushed in Class Seventeen tries the same command by habit; GitHub refuses it outright, and the lesson lands without anyone having to relive the outage.

A small CODEOWNERS file follows, routing anything under /infra/network/ to the two people who understand the VNet, and the README gets its first honest pass: what Campux's platform repo is, how to deploy from it, and the branch rules a contributor must expect. Campux now has, for the first time, a repository a new hire could join on a Monday and be productive in by lunch — which is precisely the thing the reader is learning to build for anyone.

Watch · Microsoft Learn

The official module, and a CAMPUX overview

Read or work the module first; watch the overview to see it move
Microsoft Learn · Modules

Introduction to GitHub
learn.microsoft.com/training/modules/introduction-to-github/

Manage repository changes by using pull requests on GitHub
learn.microsoft.com/training/modules/manage-changes-pull-requests-github/

CAMPUX overview video

A short walkthrough of opening a pull request, running a review, and switching on branch protection will live here. Video to be added.

Lab 1 · Your first repository

The GitHub round-trip, once, end to end

~12 minutes · a web browser · Git installed on your machine

Before you touch the campux repo, walk the whole loop once on a throwaway one: sign up, create it on GitHub, clone it into your Downloads folder, add a file, and push it back. Do this until create → clone → commit → push → confirm is muscle memory.

  1. Go to github.com and create an account (or sign in if you have one). A free account is all you need.

    What to notice: the username you pick becomes part of every repository URL — github.com/<you>/<repo>. Choose one you would put on a résumé, because recruiters will read it.
  2. Click New (or the + at top-right → New repository). Name it hello-github, leave it Public, tick Add a README file, and press Create repository.

    What just happened: GitHub now hosts a repository with exactly one commit — the README. Adding that README matters: it makes the repo non-empty, so you can clone it straight away.
  3. On the repo page, click the green Code button and copy the HTTPS URL. In a terminal, go to your Downloads folder and clone it:

    cd ~/Downloads
    git clone https://github.com/<you>/hello-github.git
    cd hello-github
    What just happened: git clone made a local folder that is already wired to GitHub — it set origin for you, so no git remote add is needed. Cloning is how you start on a repo that already lives on GitHub.
  4. Create an empty file, then stage, commit with a message, and push:

    touch notes.txt
    git add notes.txt
    git commit -m "Add empty notes file"
    git push
    What just happened: the change travelled working → staged → committed → GitHub. git push needed no branch name because the clone already set up tracking against origin/main.
  5. Confirm it arrived: refresh the repository page on github.com.

    The lesson: notes.txt now appears in the file list, and your commit message shows in the history. That is the whole loop — create, clone, edit, add, commit, push, verify on GitHub. Everything else this class is a safer, reviewed version of it.
Note · clone is for a repo that already exists on GitHub; it sets origin automatically. If instead you already have a local repo with no remote — like campux-platform from Class Seventeen — you connect it the other way: git remote add origin <url> then git push -u origin main. Lab 2 uses exactly that path.
Lab 2 · Pull request

Open, review, and merge a PR

~12 minutes · a GitHub account · the campux-platform repo from Class Seventeen

Now take the existing local repo from last class online — using git remote add, the path Lab 1 flagged — then run one change through the full ritual: branch, PR, review, merge. This is the loop you will repeat for the rest of your career.

  1. Create a new empty repository on GitHub named campux-platform (this time without a README, since the local repo already has one), then connect and push your local one:

    git remote add origin https://github.com/<you>/campux-platform.git
    git push -u origin main
    What just happened: your existing local ledger now has a home on GitHub. Because the repo already lived on your machine, you connected it with remote add rather than cloning. origin is the remote; main is the branch everyone will collaborate on.
  2. Make a change on a branch and push it:

    git switch -c add-readme-intro
    printf "\n## What this is\nCampux's infrastructure, as code.\n" >> README.md
    git commit -am "Add README intro"
    git push -u origin add-readme-intro
    On screen: GitHub prints a link to open a pull request for the branch you just pushed. The branch exists remotely; nothing has touched main yet.
  3. In the browser, open the pull request. Read the Files changed tab, add a comment on a line, then approve it under Review changes.

    What to notice: the PR shows the exact diff, the discussion, and — this being a solo repo — lets you approve your own. On a real team, that approval must come from someone else. The diff, not the branch, is the thing under review.
  4. Merge the pull request, then bring main up to date locally:

    git switch main
    git pull
    The lesson: the change reached main only through the PR — described, reviewed, recorded. Delete the branch when GitHub offers; the PR keeps its history forever.
Lab 3 · Branch protection

Make the rules refuse the foot-gun

~10 minutes · same repo · Settings → Branches (or Rules → Rulesets)

Turn the etiquette of §3 into a property GitHub enforces, then prove it works by trying — and failing — to push straight to main.

  1. In the repo, go to Settings → Branches → Add branch ruleset (or classic Add rule). Target the main branch.

    What to notice: the list of rules is exactly Table 1 — each a checkbox that turns a hope into a guarantee.
  2. Enable Require a pull request before merging with 1 required approval, and Block force pushes. Save.

    What just happened: main is now guarded. No direct push, no force push, no merge without a reviewed PR — the platform will enforce it regardless of who forgets.
  3. Try to violate the rule on purpose — commit straight to main and push:

    git switch main
    echo "sneaky" >> README.md
    git commit -am "direct to main"
    git push
    On screen: the push is rejected — "protected branch hook declined". The exact command that erased a colleague's work last class is now impossible. Undo the local commit with git reset --hard origin/main.
  4. Optional: add a .github/CODEOWNERS file (via a PR), then switch on Require review from Code Owners and watch the owner be requested automatically on the next PR.

Note · a repository must be public, or on a paid plan, for branch protection on private repos — a free private repo may not expose every rule. Rulesets are the newer surface; classic branch protection still works identically for this lab.
On the job

The repo enforces the conversation

You · Cloud Engineer · a teammate's PR is in your queue

A pull request lands in your queue. You read the diff, leave two questions and one "nice," and request a small change before you approve. Because CODEOWNERS routed it to you and branch protection blocks the merge until review passes, the repo enforces the conversation — and quality stops depending on everyone remembering to ask for it.

Class Eighteen

Examination

Four drills, then two situations. The situations have no marking scheme — write your answer before you reveal the reasoning, or the exercise is worthless. Nothing is stored; this is between you and the page.

Drill 01Recall · branch protection
A branch rule on main has "Require a pull request before merging" enabled. What does it forbid?
Marked

A. This rule closes the direct-push door: nothing lands on main except through a PR. C is a different rule ("Require status checks to pass"); requiring approvals is another again. The reason to know them individually is that each is a separate checkbox — a repo can require a PR yet still merge with zero reviews and red checks if you stop there. Protection is only as strong as the specific rules you turn on.

Drill 02Recall · CODEOWNERS
You add a CODEOWNERS file listing owners for /infra/network/, but their approval is never actually required. Most likely cause?
Marked

B. On its own, CODEOWNERS only auto-requests the right reviewers; it becomes mandatory only when the branch rule "Require review from Code Owners" is enabled. The other classic failure — worth holding alongside this one — is an owner who lacks write access, whom GitHub silently drops as an invalid reviewer. Both bugs look identical from the outside: the file is there, the gate never closes. Wire the rule and grant the access.

Drill 03Select three
Which three are marks of a healthy code review?
Marked

Address the change, separate must-fix from nit, and ask rather than decree. The two false options are the ones that quietly rot a team: withholding approval over taste turns review into the step everyone dreads, and fast-approving a huge PR launders a false sense of safety — a 900-line diff gets skimmed, not reviewed, which is worse than no review at all. Good review protects the codebase and the human; drop either and people route around you.

Drill 04Spot the error
A memo proposes the protection settings for main. Every line but one is sound. Which line quietly defeats the point?
PROTECT main — proposed settings

1.  Require a pull request before merging
2.  Require 1 approving review
3.  Require status checks to pass (bicep-validate)
4.  Allow force pushes for repository admins
5.  Block branch deletions
Marked

Line four. It re-opens the exact door the whole ruleset exists to close. The moment admins can force-push, the shared-history disaster of Class Seventeen is possible again — and incidents rarely happen to the careful junior, they happen to the tired admin at the end of a long day, who has the most power and the least sleep.

The correct posture is the opposite: block force pushes for everyone, and switch on "Do not allow bypassing" so the rules bind admins too. A rule that a privileged account can step around is not a rule; it is a suggestion with good intentions. Lines one, two, three and five are all fine — modest, but real.

Situation 01Write before you reveal
You leave a few review comments on a teammate's pull request — nothing harsh, mostly questions. They reply defensively, then message you privately that they feel you are "always picking at" their work. What do you do?
Writing it down first is the exercise. Reading the answer first is not.
Reasoning

Separate the relationship from the diff — and tend the relationship first. Whatever the code merits, a teammate who feels attacked will not hear a word about it, so the review is stalled until the human part is repaired. Take the conversation off the PR thread and into a real one; a public back-and-forth only raises the stakes for both of you.

Concede your share before you defend the substance. A strong answer opens by owning the part you control: maybe the comments read colder than you meant, maybe there were too many, maybe you flagged nits with the same weight as real concerns. You are not surrendering the technical points — you are removing the reason they cannot be heard. "I could have framed those better" costs you nothing and buys back the review.

Then fix the system, not just the moment. The durable answer is to make reviews feel less personal by design: label blocking comments versus optional nits, keep them about the change, and let the branch rules — not you — be the thing that "says no." When the platform enforces the standard, a comment stops feeling like one person picking on another and becomes what it should be: two people getting a change safe to ship.

Situation 02Write before you reveal
A senior engineer, mid-incident, snaps: "Branch protection is bureaucracy — let me just push the hotfix straight to main so we can stop the bleeding, and we'll do the PR afterward." You have the admin toggle. What do you say?
The trap is the premise: that the rules and the speed are opposed.
Reasoning

The trap is the premise. The request assumes the protection and the fix are in tension — that going fast means going around the rules. They are not opposed. A PR with one approval and a green check takes a couple of minutes, and those minutes are exactly when a second pair of eyes is most valuable: the two-line hotfix written under pressure is the change most likely to be wrong, and the incident is the worst time to skip review, not the best.

Offer the fast path that keeps the guardrail. Open the branch, push the fix, open the PR, ping someone to approve it now. If the team genuinely needs an emergency lane, that is a designed thing — a documented break-glass with an approver and an audit trail — not an admin quietly flipping the rule off at 2am and hoping to remember to flip it back.

Name what "afterward" really means. "We'll do the PR afterward" is how the rule dies — the afterward never comes, and the next person learns that main is pushable when someone senior is stressed. The whole value of protection is that it holds precisely when people are tired and rushed. Hold it, help them ship in three minutes, and write the post-incident note that gives them a real emergency process instead of a disabled one.

Examination record · first attempt
0/4
Class Eighteen · Complete
Retain this much

Five things worth carrying out of this class

  1. The pull request is the unit of professional work: a described, reviewed, checked, recorded slice of change. The commit is raw material; the PR is the accountable thing.
  2. Review the change, not the person. Ask rather than decree, separate must-fix from nit, and approve when it is good enough — not perfect.
  3. Branch protection turns etiquette into a property: require a PR, require approvals, require checks, block force pushes — and "do not allow bypassing" so the rules bind admins too.
  4. CODEOWNERS routes changes to the people responsible for them — but only bites when "Require review from Code Owners" is on and owners have write access.
  5. A README that answers the interviewer — what, why, how to run, how to contribute — is the closest thing to a demonstration of how you work.
Notes
  1. The pull request is a GitHub invention (GitLab calls the same thing a "merge request", which is arguably the better name — you are requesting a merge, not a pull). Git itself has no concept of it; the underlying operation is still an ordinary merge. What the platform adds is everything around that merge — the diff view, the discussion, the reviews, the required checks, and the permanent record — which is precisely the part that makes collaboration safe.
  2. GitHub is mid-migration from "branch protection rules" to "rulesets", which do the same job with more flexibility — layered rules, targeting multiple branches by pattern, and clearer bypass lists. For everything in this class the two are interchangeable, and both live under Settings. If your screen does not match the menus here exactly, that is the migration, not you; the concepts — require a PR, require review, block force pushes — are stable even as the UI moves.
  3. On free plans, branch protection on private repositories is limited; a public repo, or a paid plan, exposes the full set of rules. Treat the specific plan boundaries with suspicion — GitHub moves them periodically — but treat the direction as settled: the industry expectation is that main is protected, and an unprotected default branch reads as an amateur repository regardless of the reason.