Better Pull Requests & Merge Requests With Templates

How do you communicate with your team about proposed code changes? Patrick explains how templates can build structure and efficiency.

One of the most critical roles we play as developers is to clearly communicate with our team. When I propose a change or addition to a codebase as a project contributor, I want the team members who review the code to understand what I was trying to achieve with that work. And as a project maintainer, I want those who propose code changes to explain their changes and let me know me how to test the code.

I could communicate these expectations in many different ways. But unless I’ve documented them somewhere, those expectations are probably more of a “nice-to-have” rather than something that will be an accepted standard practice for a project. And having a standard way of doing things—especially a documented, standard way of doing things—is a great step forward to helping your team communicate more clearly.

So, how do we make communicating around proposed code changes more clear? As project maintainers, we can provide guidelines for contributors about our expectations and be sure that those guidelines are seen every single time someone proposes a code change.

For example, let’s say that your team is hard at work on a new web app that should look great and work well on a number of different devices and browsers. So you know that browser and device testing is going to be important. In fact, the client has helpfully indicated that certain browsers and devices should take precedence over others, and they’ve shared that list with your team.

Having a list of known things to test against is great! But, how does the team make sure that list gets seen by everyone who will be committing code to the project and that none of agreed-upon browsers or devices are being missed or forgotten? Wouldn’t it be helpful if that list became a “checklist” of sorts—one that showed up every time a member of your team did a code review for this project?

Well, if your team uses GitHub or GitLab as your version control host of choice, your team is in luck. Both of these hosted Git services offer the ability to enable “templates” for proposed code changes. These templates are boilerplate text or other content that will automatically show up in the change request form when project collaborators issue a pull request or a merge request against a code repository. What a perfect place to keep that browser checklist!

Pull Request? Merge Request? Huh?

It might be helpful for me to explain some of the vocabulary that I’ll be using throughout this post. In GitHub, a proposed code change is called a “pull request.” In GitLab, a proposed code change is called a “merge request.” Although the two services use different phrases, the same concept applies: Someone is proposing that a change be made to a codebase. Often, folks will shorten these phrases to “PR” for pull request or “MR” for merge request. When you begin the process of submitting a pull or merge request, you’re presented with a form to fill out.

Initiating a new pull request on GitHub.
Initiating a new pull request on GitHub
Initiating a new merge request on GitLab.
Initiating a new merge request on GitLab

Here’s where our new concept of pull and merge request templates come into play: What if we could automatically pre-populate the “Leave a comment” field with our browser and device checklist rather than seeing a blank form? Or what if we could automatically pre-populate that area with headings that describe what this pull or merge request is proposing, how to test it, and the potential problems that could arise when the reviewer is looking at the code?

Getting Started with Pull and Merge Request Templates

Using our browser and device list as an example, let’s discuss how these templates for pull and merge requests function inside of GitHub and GitLab.

First, we take our browser and device list in an already-existing repository, and turn it into a type of file that these services will automatically recognize as a “template” to use for pull and merge requests, rather than just another file associated with the repository. Specifically, we need to create a Markdown file and place our checklist in there.

An example of our newly created markdown file with our browser testing checklist
An example of our newly created markdown file with our browser testing checklist.

From here, GitHub and GitLab have different requirements around naming conventions for these markdown files and where they should live in our repositories. Both services also differ on how they handle repositories with single templates versus multiple templates.

Let’s talk about each service and how to work with them.

Creating a Single Pull Request Template for a GitHub Repository

For a GitHub-hosted repository to automatically recognize a pull request template and pre-populate the new pull request form, the template must be a markdown file. The name of the template and its location in your repository are also important. Your template file can exist in a few places:

  • In your project’s root, with the file name PULL_REQUEST_TEMPLATE.md
  • In a docs directory, with the file name PULL_REQUEST_TEMPLATE.md
  • In a “hidden” .github directory, with the file name PULL_REQUEST_TEMPLATE.md

If your template has a different file name or exists outside of the places listed above, GitHub will not automatically pre-populate new pull request forms with the template’s contents.

Once you have created the PULL_REQUEST_TEMPLATE.md and saved it in one of the proper locations, you must merge the newly created template into your repository’s master branch before GitHub will automatically recognize and use it when opening new pull requests.

An example of a new GitHub pull request form, pre-populated with the contents of our pull request template file
An example of a new GitHub pull request form, pre-populated with the contents of our pull request template file.

Creating Multiple GitHub Pull Request Templates for a Repository

What if having only one pull request template for the whole project doesn’t make sense? What if the template you created is a no-brainer for most of the project, but then there’s a new feature and the team wants different content to pre-populate in that branch’s pull request form?

The good news is that GitHub repositories can have multiple pull request templates. But this process requires a little extra effort to be truly awesome.

Why? Because when you’re using a single pull request template, GitHub automatically pre-populates each new pull request with the template’s content, as long as you’ve named and stored it correctly. But when you’re looking to use multiple templates, GitHub does not automatically know which template takes precedence. As I’m writing this, there is no “create new pull request” button that will pre-populate the pull request form with the template contents of your choosing. Nor is there a way via the GitHub interface to see what templates are available and to choose the appropriate one for your pull request.

While the workflow for this is a bit cumbersome, here’s how you can make use of GitHub’s multiple pull request templates:

  1. First, in your repository’s root, create a directory named PULL_REQUEST_TEMPLATE. Do not name that directory anything else or put it in a different location, otherwise, GitHub will not recognize any of your templates.
  2. Then place your template markdown files within that PULL_REQUEST_TEMPLATE directory.
  3. Name these files however you like, but know that you’ll refer to these file names in the URL that you’ll be manually editing and/or creating when you issue a new pull request.

Now, here’s the cumbersome part: For pull request forms to be pre-populated with template content, contributors will have to manually create and navigate to a particular URL when issuing pull requests.

For example, let’s say that I have a repository called example-repo that has multiple pull request templates to choose from, including a generic template called default.md. I’ve been working on a branch called prbranch, and the code there is ready to be reviewed and merged into the master branch. In order for my pull request form to be pre-populated with the contents from default.md, I need to navigate to a URL that looks like this: https://github.com/sparkbox/example-repo/compare/master...prbranch?quick_pull=1&template=default.md. That URL structure indicates that I’m in my example-repo, that I’m creating a pull request by comparing the code in prbranch against master, and I want to automatically pre-populate the pull request form with the contents of my default template.

GitHub has some brief documentation about this URL structure, namely around query parameters (the ? in their URLs) for issues and pull requests, but at the time of writing, that documentation doesn’t note that the & should be used for referring to a particular PR template.

In my opinion, the current process is a lot to remember. It’s so heavy a burden for the contributor to bear that I’m hesitant to recommend you use GitHub’s multiple templates feature. If your team is using multiple pull request templates, though, and you’ve figured out a good workflow for this, we’d love to hear from you!

Creating GitLab Merge Request Templates for Repositories

The GitLab workflow around merge request templates is a bit different than GitHub’s pull request template workflow, and the language is slightly different, too. In GitLab, if you want to create a single or “default” merge request template, you don’t necessarily have to create a standalone markdown file in your repository—you can create a template via your repository’s settings panel in the GitLab UI. GitLab uses the phrase “description template,” rather than simply calling it a “template.”

The merge request settings section of GitLab’s project “Settings” panel.
The merge request settings section of GitLab’s project “Settings” panel.

Outside of using the GitLab UI to create a default template, GitLab also offers the option to create markdown files and make them part of a project’s repository. And, GitLab repositories can make use of single or multiple templates.

In order for GitLab to recognize your templates and pre-populate merge request forms:

  1. First, in your repository’s root directory, create a directory named .gitlab.
  2. Inside of that .gitlab directory, create a directory named merge_request_templates.
  3. Inside your .gitlab/merge_request_templates directory, you can have one or many template files, but they must be markdown files.

Once you’ve created your file or files in that particular location and you merge those files into your master branch, your repository will automatically be aware of your merge request templates.

Then when a contributor issues a new merge request, they’ll see a dropdown that encourages them to “choose a template” and pick which template suits their merge request.

Choosing a description template when issuing a new merge request on GitLab.
Choosing a description template when issuing a new merge request on GitLab.

In my opinion, GitLab’s description template picker is a great addition to their merge request UI. It’s much simpler than manually editing a URL while issuing a pull request on GitHub. The intentional placement of a template picker gives contributors the awareness that not only do templates exist, but also that they can pick one of the available templates to suit their merge request needs.

Your (Template’s) Presence is Requested

So, what does a pull or merge request template look like once it’s made its way into your repository? Any time a new pull or merge request is issued, the description portion of the request form will be pre-populated with the contents of your template file.

An example of using a browser testing checklist as part of a GitHub pull request template
An example of using a browser testing checklist as part of a GitHub pull request template.

A Humble Request

In its user documentation, GitLab introduces templates by explaining that “a properly submitted issue is more likely to be addressed in a timely manner by the developers of a project.” By creating templates for pull and merge requests, we can help encourage contributors to communicate more effectively with their teams by noting what’s new or changed, give testing instructions to reviewers, or even help to ensure that code changes have been thoroughly vetted.