GitHub PR templates are a surprisingly effective way to automate the why of a change, not just the what.
Here’s a pull request for adding a new GET /users/{id} endpoint to our user service.
{
"title": "feat: Add GET /users/{id} endpoint",
"description": "This PR introduces a new endpoint to retrieve user details by their unique ID.\n\n### What does this PR do?\n\n- Adds a new route `GET /users/{id}`.\n- Implements logic to fetch user data from the database.\n- Includes basic error handling for non-existent users.\n\n### How to test this change?\n\n1. Start the user service locally.\n2. Make a GET request to `/users/123` (replace `123` with a valid user ID).\n3. Verify that user details are returned.\n4. Make a GET request to `/users/999` (replace `999` with a non-existent user ID).\n5. Verify that a 404 Not Found error is returned.\n\n### Related issues\n\nCloses #456",
"labels": ["feature", "api"],
"assignees": ["octocat"],
"reviewers": ["monalisa"]
}
This example shows a JSON object representing a pull request. In reality, GitHub’s PR templates are Markdown files that are automatically populated into the PR description field when a new PR is opened against a branch. The magic happens in the .github/pull_request_template.md file in your repository.
When someone opens a pull request, this template is injected into the description box, guiding them on what information to provide. This isn’t just about making PRs look pretty; it’s about ensuring that every change has context.
The core problem PR templates solve is the "I don’t know what this does" or "Why was this change made?" question that plagues code reviews. By providing a structured format, you force contributors to articulate the purpose, testing procedure, and any related issues. This transforms a passive review into an active understanding of the change.
Let’s break down how it works internally. When a PR is created, GitHub checks for the presence of a pull_request_template.md file in specific directories (.github/ or docs/). If found, the content of that file is used to pre-fill the PR’s description.
The template itself uses Markdown, which is incredibly flexible. You can include:
- Headings (
#,##): To structure the information. - Lists (
-,*): For steps or bullet points. - Code blocks (```): To show example commands or snippets.
- Links (
[]()): To reference issues or external documentation. - Checkboxes (
- [ ]): For creating actionable checklists.
Here’s a more detailed look at a common template structure:
## What does this PR do?
<!-- Briefly describe the changes introduced by this PR. -->
### Changes
- [ ] Added new feature X
- [ ] Fixed bug Y
- [ ] Refactored module Z
### How to test this change?
<!-- Provide clear, step-by-step instructions on how to test the changes. -->
1. Step 1
2. Step 2
### Related issues
<!-- Link to any relevant issues. -->
Closes #123
Fixes #456
The key is to make the template actionable and informative. Use placeholders like <!-- ... --> for comments that guide the author. The checkboxes are excellent for ensuring essential review steps are considered.
The most surprising thing about PR templates is how much they improve the quality of the code review itself, beyond just documentation. When authors are prompted to think about "How to test this change?", they often uncover edge cases or flaws in their implementation before a reviewer even looks at it. This shifts the burden of initial validation from the reviewer to the author, making reviews more efficient and focused on architectural concerns and code elegance.
Ultimately, a well-crafted PR template standardizes the communication surrounding code changes, making reviews faster, more thorough, and more insightful for everyone involved.
The next step after standardizing PRs is often to automate checks based on this structured information using GitHub Actions.