Skip to content

Pull Requests, Reviews, and Protected Branches

A Pull Request (PR) asks a hosting platform to compare a source branch with a target branch so people can review a proposed integration. The commits and branches are Git concepts; the PR, comments, reviews, and merge button are GitHub features.

head / compare: feature/navbar ── proposed change ──> base: main

Opening a PR does not merge anything. The target branch changes only when the PR is merged or someone separately updates it. “Able to merge” means the platform currently sees a possible integration, not that it already happened.

A PR gives the team one place to inspect the diff, discuss behavior, request changes, review test results, and decide when the work is ready. It creates a visible decision trail that a quick local merge does not provide by itself. For a backend change, reviewers might check API contracts, migrations, authorization, and tests before allowing the target branch to move.

PRs do not automatically make code safe. Review must be substantive and automated checks must exercise the relevant behavior.

  1. Create a feature branch, commit, and push it.
  2. Open a PR from the feature branch (head) into main (base). Write a title and description explaining the change and test evidence.
  3. Reviewers comment, approve, or request changes. New commits pushed to the same head branch appear in the open PR automatically.
  4. After requirements pass, an authorized person merges the PR using an allowed merge method. Alternatively, close it without merging.
  5. Teammates fetch or pull the updated base branch. Delete the finished head branch only when it is no longer needed.

Example preparation:

Terminal window
git switch -c feature/navbar
git add src/Navbar.cs
git commit -m "feat: add navigation bar"
dotnet test
git push -u origin feature/navbar

On GitHub, choose the correct base and compare branches. A reversed direction proposes updating the feature from main rather than integrating the feature into main.

  • Comment: discuss without approving or blocking through a review decision.
  • Approve: signal that the reviewer accepts the current change.
  • Request changes: ask the author to fix issues before approval.

Approval alone may still be insufficient: required checks, unresolved conversations, a stale approval after new commits, or branch rules can keep merge disabled. Exact rules vary by repository.

GitHub may offer a merge commit, squash merge, or rebase merge, depending on repository settings. They produce different commit histories. The earlier merge lesson explains fast-forward, true merge, and squash. Do not assume pressing the merge button always creates the same history shape.

After GitHub merges the PR, main advances on GitHub. A developer’s local main remains where it was until fetch or pull updates it:

Terminal window
git switch main
git pull --ff-only origin main

If the local branch has diverged, inspect it rather than forcing an update.

The PR can usually remain open even if GitHub cannot merge it automatically. The conflict means the base and head have changes that need a human decision. GitHub’s browser conflict editor handles some simple cases; complex changes are better resolved in a local clone.

The safest common team workflow is to update the head feature branch and let the existing PR refresh:

Terminal window
git fetch origin
git switch feature/navbar
git merge origin/main

If Git stops, inspect and edit the conflicted files, remove conflict markers, run tests, then finish:

Terminal window
git status
git add src/Navbar.cs
git merge --continue
dotnet test
git push origin feature/navbar

The open PR now contains the resolution commit. Reviewers can inspect it and merge through the normal protected-branch path. If the merge approach was wrong, use git merge --abort before finishing, provided you understand the state of any pre-existing local edits.

One lecture example resolves the feature branch, then merges it locally into main and pushes main directly. That can work in an unprotected repository, and GitHub may mark the PR as merged if its commits reach the base. But it bypasses the intended PR approval and checks and can fail on a protected branch. For a team using PR governance, push the fixed feature branch and merge the PR on GitHub instead.

GitHub branch protection rules and rulesets can enforce repository policy on branches matching a name or pattern. Teams often protect main so the rule is not merely “please use a PR.” Depending on settings and plan, rules may:

  • Require a PR and a specified number of approving reviews.
  • Require passing status checks before merge.
  • Block force pushes or deletion.
  • Require resolution of review conversations or a linear history.
  • Restrict who may push, with exceptions or bypass permissions.

The exact settings UI, availability by plan, and behavior of administrators or bypass roles can change. See GitHub’s current protected-branch documentation.

Suppose the repository requires a PR and one approval for main:

  1. Sara cannot push directly to main if the rule applies to her. She pushes feature/readme-fix instead.
  2. Sara opens a PR into main. Opening it alone does not satisfy the review requirement.
  3. Ahmed reviews, comments if needed, and approves after the change is ready.
  4. Required checks must also pass. Then a person with merge permission completes the PR and GitHub updates main.

Do not generalize “the author can never approve their own PR” without checking the effective policy. The key point is that a required independent approval must be supplied by an eligible reviewer; bypass permissions and review rules affect the result.

Branch protection does not magically guarantee a working main. The checks must cover the important behavior and the team must not misuse bypass rights.

For a small project with no protected branch, teammates may review verbally and merge locally:

Terminal window
git switch main
git pull --ff-only origin main
git merge feature/navbar
dotnet test
git push origin main

That is a valid Git workflow when policy permits it. It has less built-in review evidence and no automatic approval gate. Choose the governance level intentionally rather than assuming every repository has the same rules.

  • Thinking an open PR has already changed main.
  • Opening the PR with head and base reversed.
  • Assuming an approval alone overrides required checks or conflicts.
  • Resolving conflicts by pushing directly to protected main and bypassing the PR.
  • Deleting the head branch while someone still needs to add changes.
  • Assuming local main updates as soon as a GitHub PR is merged.
  • Treating every green check as proof that business behavior is correct.

A PR is a review request layered on top of Git branches. Push more commits to the same head branch to update it, including conflict resolutions. Merge only after the repository’s review and check requirements are met. Protection rules make those requirements enforceable, but the exact policy is repository-specific.

  1. What are the head and base branches in a PR that adds a feature to main?
  2. Does opening a PR immediately merge it?
  3. Where should you normally push a local PR conflict resolution?
  4. Why might merge remain blocked after one approval?
  5. Why is directly pushing a local merge to protected main the wrong resolution path?