This guidebook is written following the diátaxis “how-to guide” style. And because this document reflects how we work in the Seedcase Project, it is living and constantly evolving. It won’t ever be in a state of “done”.
Pull requests (PRs) are how we propose, review, and discuss changes before they become part of a project on GitHub. In fact, we require that all changes to a repository on GitHub go through a pull request. We use pull requests for several reasons. They:
- Help to maintain code and text quality and minimise the risk of errors, typos, or other issues.
- Enable effective collaboration by allowing changes to be reviewed and discussed before they become a part of a project.
- Provide a structured process for integrating new developments into a project.
As the American software developer (and founder of Stack Exchange) Jeff Atwood wrote:
“Peer code reviews are the single biggest thing you can do to improve your code. If you’re not doing code reviews right now with another developer, you’re missing a lot of bugs in your code and cheating yourself out of some key professional development opportunities. As far as I’m concerned, my code isn’t done until I’ve gone over it with a fellow developer.”
This section covers the practices we follow for creating and reviewing pull requests.
What is a pull request?
To understand pull requests, it helps to first understand branches. When you work on a project in Git, there is a default branch (usually called main) that holds the current, stable version of the project. Instead of making changes directly to main, you create a branch—think of it like making a copy of a document so you can draft changes without touching the original. A branch allows you to work on your changes independently, and, when you are happy with your changes, you request that the project pulls the changes from your branch into the project’s main branch. That request is called a pull request (PR).
A PR gives your collaborators the opportunity to review your changes, ask questions, and suggest improvements before the changes become part of the project. This review process helps catch mistakes, maintain quality, and keep your collaborators informed about what is changing and why. PRs also become durable project documentation: future contributors can use their descriptions and discussions to understand why a change was made.
The diagram below Figure 3.1 shows this in practice. A person creates a branch called docs/add-pr-guide to work on their changes. The dots represent commits, which are saved snapshots of their work. When ready, they open a PR. After review and approval, their changes are merged back into the main branch of the project.
Generally, the PR process follows these steps:
- Create a branch for your changes.
- Make your changes and commit them to the branch.
- Open a pull request on GitHub to propose merging your changes into
main.
- Review and discuss the changes with your collaborators.
- If the changes are approved, merge the PR into
main. If not, make further changes, update the PR, and request another review.
This workflow is called the GitHub flow and is a widely used and effective collaboration strategy for projects of all sizes.
Creating a pull request
Before making changes, create a short-lived branch from an up-to-date main branch. Keep the branch focused on one issue or logical change so that its PR will also be focused.
Branch naming conventions
Branch names should be lowercase, use hyphens between words, and follow the format {type}/{short-description}. Write the description in the imperative. The type is based on the Conventional Commits types (e.g., docs, fix, feat, refactor). For example:
docs/add-pr-workflow-guide
fix/broken-link-in-readme
refactor/update-template-structure
The Conventional Branches VS Code extension can help create a correctly formatted branch name from the Command Palette. In our templates, e.g., template-python-package, we’ve added the VS Code settings for the extension to follow the format described above.
Prepare the change
Start with creating an issue (or comment on an existing one) before investing substantial time on an implementation. Use the issue to describe the problem, expected behaviour, and proposed direction. This allows the team to agree on the scope and approach before work begins so that effort is not wasted on substantial re-writes or even PR rejection.
Before creating a PR:
- Review all the changes made yourself, not only the most recent changes.
- Remove accidental or unrelated changes.
- Run the repository’s automated formatting, linting, tests, and other checks (found in the
justfile).
- Check that code and text communicate their intent without relying on the PR description.
- Add or update tests and documentation when relevant.
How to create a PR
When you’ve made your changes on a branch, there are a few ways to make a PR. We use two ways: through VS Code and through the GitHub website. Using the GitHub website is a fairly straightforward way of making a PR: You go to the pull request tab of the repository, click the “New pull request” button and follow the instructions there.
Creating a PR through VS Code, however, is usually faster, though it requires some setting up and practice. To be able to create pull requests to GitHub from within VS Code, you need to install the extension GitHub Pull Requests and Issues. You can find and install this extension by going to the Extension view in the left sidebar of VS Code and search for it. Once you have installed it, VS Code will prompt you to link to your GitHub account by signing in and giving access.
Now, you can use the command palette (Ctrl+Shift+P or Cmd+Shift+P) and search for “GitHub: Create Pull Request” to create a pull request from the current branch you are working on. This will open a new pull request form in the sidebar where you can fill out the title, description, and other details of your PR before submitting it. If you’re comfortable with the Terminal, you can also use that from within VS Code to push your changes to GitHub.
When to create a PR
You can create a PR as a draft once you have made meaningful changes and have a clear idea of the implementation. An early draft makes the work visible and lets you ask for early feedback if needed before committing too much time to a specific approach. Mark it as a draft while it is incomplete, and add to the PR description what feedback would be useful.
Only mark the PR ready and request a review after the work is complete, self-reviewed, and in a state that can be tested. Reviewers should not have to act as the author’s formatter, linter, or first round of quality assurance.
Keep PRs small
Each pull request should represent a single, focused change. This makes it easier for reviewers to understand the changes and provide meaningful feedback. A small (atomic) PR might be:
- Adding a new section to a document.
- Fixing a bug or typo.
- Refactoring a specific component or function.
- Adding or updating a single feature.
Avoid combining unrelated changes into a single PR. If you find yourself writing “and” in your PR description to connect two separate ideas, consider splitting them into separate PRs. Smaller, focused PRs are quicker to review, easier to test, and simpler to revert if something goes wrong.
There is no strict guideline for how big a single PR can be in terms of the lines of code changed; the most important is to keep logically connected changes together in the same PR. Generated files and a logically indivisible change may justify a larger change while logically separate ideas require splitting even if they change just a few lines of code. Having that said, a practical recommendation is to start asking yourself whether the PR could be broken up into a few smaller PRs when you approach 100-150 lines of code. Keep in mind that your reviewer does not have the same context as you do, and they have not seen the changes gradually progress as you have, so smaller PRs makes it easier for them to understand what is going on. If you think a large PR should not be split, explain why in the PR description, so this is clear to the reviewer. More guidelines on how to write small PRs could be found in e.g. Google’s engineering pracitces.
Avoid stacked PRs, where one open PR targets the branch of another open PR, unless there is an exceptional reason to use them. Dependencies between PRs make review and merging harder. We prefer independent changes; otherwise, clearly identify the dependency and required merge order.
Writing a good PR description
A good PR description helps reviewers understand the context and purpose of the changes. Our repositories include a pull request template to make it easier to follow the same description structure when creating a PR. In the title, follow the Conventional Commit format, for example fix: prevent overwriting raw files. Because we squash PRs, this title becomes the commit subject on main. Therefore, it’s important that you ensure, before you merge a PR, that the title follow Conventional Commits. Otherwise, the changelog and potential version update won’t be auto-generated.
In the description field, aim to cover:
- What: Briefly describe the changes you made.
- Why: Explain the motivation or reasoning behind the changes.
- How: If the changes are not straightforward, describe the approach you took.
- Evidence: Include tests, usage examples, or before-and-after screenshots when they help demonstrate the changed behaviour.
- Considerations: Describe why alternative approaches were rejected, try to address concerns/confusions you might foresee, or raise outstanding questions to clearly define what is yet to be decided on.
If the PR addresses an existing issue, reference it by writing Closes #<issue-number>, e.g., Closes #2 in the description. This automatically links the PR to the issue and closes the issue when the PR is merged.
Keep the description concise but informative, with detail proportional to the complexity of the change. A few sentences are often enough for a small PR. A deep or unusually complex change may need a longer explanation of constraints and design choices so that the reviewer does not have to reconstruct the author’s reasoning from the commit diff alone. Writing informative commit messages will help the reviewer if they need additional detail about a specific change in the PR.
Do not duplicate a full bug report or design discussion from an issue. Link to it and summarise only the context needed to review the concrete implementation. Keep general questions and alternative future work in targeted issues rather than expanding the scope of the PR discussion.
Indicate in the description whether the PR needs a quick or thorough review. A quick review might be suitable for small changes like typos, while a thorough review is better for larger or more complex changes.
Assigning assignees and reviewers
When you create a PR, you should assign an assignee and request reviewers using the options in the sidebar on the right side of the PR page on GitHub:
- Assignees: Assign yourself to the PR. This tells others that you are the person responsible for the changes and for addressing any feedback. If you use any of our templates, like
template-website, you will automatically be assigned to the PR when you create it.
- Reviewers: Request a review from one or more collaborators. This notifies them that the PR is ready for their feedback. If you use our
template-website, it will automatically request a review from the team or people listed in the .github/CODEOWNERS file when you create the PR.
Setting both ensures that it is clear who owns the PR and who needs to look at it. We’ve set it up so this is done automatically (see our template for how). After creating the PR, add it to the relevant GitHub Project so that the team can track the work. If you’re still working on it, set it as “In progress”. Once it’s ready for review, set it to “In review”, so it’s clearly communicated to the team.
Responding to reviews
Treat review as a collaboration to improve the change, not as an obstacle to merging it. For each review comment:
- When you make the requested change, click the “resolve” button on the comment to indicate you addressed it.
- Ask for clarification rather than guessing when a comment is unclear.
- Explain respectfully when you disagree and focus on the work rather than the person. A practical tip here is to avoid using “you” in comments when it can create distance between yourself and the reviewer; either replacing it with “we” for a more collaborative tone or describing the issue more objectively without a personal pronoun altogether (this doesn’t mean it’s never good to write “you”, use your best judgment and think about how a reviewer might interpret your comment differently from your own interpretation).
- Be patient with conversations. You or your reviewer might be incorrect, or you might be misunderstanding each other. The only way to find out is through communication. Remember that you’re working towards the same goal.
- Resolve a conversation only after the concern has been addressed or everyone has agreed on the outcome.
After addressing the feedback, review all the changes in the PR and automated checks again, then re-request a review. Be grateful when a review catches a problem before it reaches main; an effective review can help you avoid the headache that would arise if one of your bugs was found in a release.
Reviewing a pull request
Reviewing pull requests is a key part of a collaborative workflow. As outlined in our task priority order, both responding to reviewer comments on your own PRs and reviewing others’ PRs are tasks of the highest priority. Timely reviews keep the work moving and prevent bottlenecks.
Reviewing changes
Review as promptly as possible, ideally within one to three working days. A slow review process causes the author and reviewer to lose context, increases the chance of merge conflicts, and might delay the rest of the team. If you cannot review within that time, let the author know (preferable in a PR comment or, alternatively, at an update meeting) so another reviewer can help.
Start by reading the linked issue and PR description. Then, review the changes and defer to individual commit messages to understand why a change was introduced. If it is hard to understand what the code does without reading the commit message, suggest that the code is rewritten or an explanatory comment is added. Focus on correctness, clarity, maintainability, tests, documentation, and whether the change stays within the agreed scope. Automated checks should handle routine formatting and syntax issues wherever possible, leaving people to focus on decisions that require judgement.
When leaving comments, be specific about what you think should change and why. Avoid vague feedback like “this doesn’t look right” and instead explain what the issue is and how it could be improved so that your feedback is both constructive and actionable. Explain both the concern and why it matters.
Comment on the work, not the author, and remain open to the possibility that you have misunderstood the change.
For Markdown files, use the “Display the rich diff” button in the “Files changed” tab to review the rendered content as well as the source.
Making suggestions
Use GitHub’s suggestion feature in the comment textbox to propose specific actionable changes directly in the code or text. This makes it easy for the author to accept your changes with a single click.
To make a suggestion, go to the “Files changed” tab and click the + icon next to a line. Then, either add a comment or make a suggestion. If you want to make a specific suggestion, click the “Add a suggestion” button (a document icon with + and -). This inserts the suggestion syntax into the comment box, where you can write your proposed change. The syntax looks like this:
```suggestion
the corrected or improved text here
```
Dealing with merge conflicts
Sometimes someone else may have made changes to the same files or lines as the changes you’ve made and merged them to main. This will lead to merge conflicts as Git can’t determine what to do with the conflicting changes. Dealing with merge conflicts requires manual editing and resolving.
There are two main ways to resolve merge conflicts:
- Use the GitHub interface to resolve the conflicts directly on the website. This is the easiest way for simple conflicts.
- Resolve the merge conflicts locally. GitHub can’t handle more complicated conflicts, so you sometimes need to resolve it on your computer and push the resolved changes to GitHub.
To handle a merge conflict locally, pull any changes from the remote repository to your local repository by using either git (e.g. git pull origin main) or through VS Code’s Git features. You can use the command palette and search for Git: Pull from and then pull from origin/main. Then, you can resolve the conflicts with the help of VS Code and with manual editing. After you’ve resolved the conflicts, you can push the changes to GitHub to update the PR.
Merging a pull request
Once a PR is approved, it can be merged into main. Merging is the responsibility of those who have write access to the main branch. GitHub offers several merge strategies (e.g., “Merge commit”, “Squash and merge”, “Rebase and merge”). We typically use “Squash and merge”, which combines all the commits in the PR into a single commit on main. This keeps the commit history clean and focused on the overall change rather than individual commits.
Before merging
- Confirm that the required reviews are approved and automated checks pass.
- Confirm that the PR branch has no unresolved conflicts with
main.
- Check that the squash commit title follows Conventional Commits.
- Edit the generated squash commit body into a durable explanation of the final change, removing temporary review notes and template text.
- Retain references to issues that should close when the PR is merged.
Delete the feature branch after merging unless it is still needed for a specific reason.
Many of the above items can be automated within GitHub’s settings. For example, there is a setting to delete branches automatically after it’s merged.
3.3.3 Comment, request changes, or approve
When you finish your review, GitHub gives you three options for submitting it:
If a reviewer requests changes, then you will need to address the feedback, update the PR, and re-request a review by clicking the “Re-request review” button in the right sidebar of the PR page. This back and forth continues until the PR is approved and ready to merge.
Keep the discussion sharply focused on the PR. If a small part prompts an extensive design discussion, create a targeted issue and continue the broader conversation there. More than about 50 comments or 25 commits is a useful signal that a PR may need to be split, although the logical scope matters more than either number.