A pull request is how you ask your team to check your changes before they land in the main branch. It is where most code review happens, and it leaves a record of what changed and why.
What a pull request is
A pull request (PR) is a proposal to merge one branch into another, usually a feature branch into main. The name says what you are asking for: you want the people who look after the project to pull your commits into their branch. GitLab calls the same thing a merge request.
The pull request most developers know isn't part of Git. Git gives you branches, commits and merges. Hosting platforms such as GitHub, GitLab, Bitbucket and Azure DevOps build the pull request on top, as a page that holds:
- the diff: every line added, changed or removed, compared with the target branch;
- a title and description saying what changed and why;
- comments, on the whole PR or on single lines of the diff;
- reviews: each reviewer's verdict;
- checks: the results of the tests, linters and builds run against the branch.
Why main stays off limits
main is the branch everyone builds on, and usually the one that gets deployed. A broken commit there breaks things for the whole team at once, so most teams never commit to it directly. Each change starts on its own branch, where it can be as messy as it needs to be until it's ready.
Branches are cheap in Git. A branch is a named pointer to a commit, so making one costs almost nothing. How long branches live and where they merge is a team choice; Branching Strategies compares the common approaches.
How a pull request works
Branch, commit, push
Say you are adding a better tuna button to an app. Start from an up-to-date main and make a branch for the work:
git switch main
git pull
git switch -c better-tuna-button
# edit the code, then:
git add .
git commit -m "Add a bigger tuna button"
git push -u origin better-tuna-buttonThe push copies your branch to the shared repository. Nothing in main has changed yet.
Open the pull request
On GitHub you can open the PR from the 'Compare & pull request' banner that appears after a push, or from the terminal with the GitHub CLI:
gh pr create --base main \
--title "Add a bigger tuna button" \
--body "Easier to tap on phones."Choose the target branch (the base), write the description and request reviewers. Many teams keep a CODEOWNERS file so the right people are asked automatically.
Review
Reviewers read the diff and leave comments, on single lines or on the PR as a whole. On GitHub, each review ends as a plain comment, an approval, or a request for changes.
Update
You don't open a new PR to answer feedback. Commit the fixes to the same branch and push again. The PR updates itself: the new commits show up in it and the checks run again.
Merge
Once the PR has its approvals and the checks pass, someone merges it and the branch's commits become part of main. Here is the branch's whole life, from leaving main to joining it again:
Platforms usually offer three ways to merge:
| Option | What lands on main |
|---|---|
| Merge commit | Every commit, plus a merge commit |
| Squash and merge | One commit with all the changes |
| Rebase and merge | Every commit, replayed, no merge commit |
Squashing keeps main to one commit per PR, and a merge commit keeps the branch's full story. Either works, as long as the team picks one and sticks to it. Once merged, the branch can be deleted.
What review is for
Automated checks tell you whether the code builds and the tests pass. A reviewer catches what a machine can't:
- a misunderstanding of what the feature should do;
- a design that will be hard to change later;
- missing tests, unhandled errors and security holes;
- code that works but that nobody else can follow.
Review also spreads knowledge: after a PR merges, at least two people understand the change. And the PR stays behind as a record. Months later, git blame leads you to a commit, the commit leads to its PR, and the PR explains why the code looks the way it does.
Platforms can enforce the process too. On GitHub, branch protection can block merges into main until a PR has a set number of approvals and every required check has passed. CI runs those checks on every push; CI/CD Pipelines covers how.
The 326-file problem
The size of a PR decides how well it gets reviewed. A reviewer can read a 50-line diff line by line and think about its edge cases. Faced with hundreds of changed files, most skim and approve anyway. That is how 'LGTM' ('looks good to me') turns into a rubber stamp: an approval that says nothing about whether anyone read the code.
Most of the fix is on the author's side:
- Keep PRs small and focused. A refactor, a dependency upgrade and a new feature are three PRs.
- Split big work into steps that each leave
mainworking: the data model first, then the API, then the UI. - Keep generated files and formatting changes out of a feature PR, or give them their own, so the real change isn't buried.
- Write a useful description: what changed, why, how you tested it, and anything reviewers should look at closely. Add a screenshot for a UI change.
- Read your own diff first, on the PR page, the way a reviewer will. It catches stray debug lines and forgotten files.
Draft pull requests help as well. A PR opened as a draft shows work in progress and runs the checks, without asking anyone to review it yet.
Reviewing well
Comment on the code, not the person. Explain why something matters, and suggest an alternative where you can. Make it clear which comments block the merge and which are preferences: putting 'nit:' in front of a comment is a common way to say 'take it or leave it'.
To run a colleague's branch locally without stashing your own work, a Git worktree gives it a folder of its own.
If a PR is too big to review properly, say so and ask for it to be split. Approving code you haven't read passes the risk on to everyone who depends on main.
Common mistakes
- Long-lived branches: the longer a branch lives, the further
mainmoves on without it, and the worse the merge conflicts get. Merge small changes often, or bringmaininto your branch regularly. - Unrelated changes in one PR: they make it harder to review, and harder to revert if one part goes wrong.
- Empty descriptions: 'Fixes stuff' makes every reviewer rebuild context you already had.
- Treating approval as the finish line: watch the deploy and the error logs after merging. Review lowers the risk; it doesn't remove it.
- Pushing straight to main 'just this once': branch protection exists so nobody has to rely on willpower.
Key takeaways
- A pull request asks your team to review a branch's changes before they merge into
main. - It is a feature of hosting platforms, built on Git branches; GitLab calls it a merge request.
- Answer feedback by pushing more commits to the same branch: the PR updates itself.
- Small, focused PRs get real reviews. Huge ones get a rubber-stamped 'LGTM'.
- Branch protection and CI can require approvals and passing tests before anything merges.