The Many Benefits of Good Pull Request Descriptions (+ How to Write One)
Submitting pull requests is a key part of our jobs as software engineers. They give us a consistent interface to review each other's code, mark progress, track bugs, and streamline testing suites and deploys. Today we'd like to talk to you about an often-ignored part of the pull request (PR) ecosystem — the PR description.
When we take time to write a good PR description we're improving our code, our teams, and our understanding. Let's walk through some of the benefits we've noticed and then talk about how to write A+ descriptions on your own.
PR descriptions make you a better programmer and teammate
Not only are PR descriptions helpful context for your team, they also train you to more concisely and effectively communicate, which is commonly an undervalued skill. Improving your communication skills will make you a better programmer and teammate.
You don't have to code all the time to level up your programming, you just need to think about it
Taking a step back to think about how you solved a problem will further cement the solution into your noggin. This will give you more tools to pull from when being faced with something similar. It will also give you a link back to a previous summary if memory fails. Being more intentional about your thinking will bring you closer to becoming the developer you've always wanted to be.
Cross-train your communication skills
Describing how your code fixes a problem is great practice for arguing your technical opinions and cross-training your communication skills. Understanding a PR on the first read will greatly decrease the time your teammates need to spend on reviewing even if they aren't well-versed in the area your PR addresses. This will encourage them to want to review your changes more often and make for faster turn around on merging your code.
Cement your own understanding of the goals
Code-switching is difficult and needs to be practiced! Coming out of your coding hole into a new space where you have to explain yourself can be jarring. If you can communicate what's missing, what's present, and what's changed then you'll prove that you understand what you're doing. This skill comes in handy when you're stuck and need to re-assess where you are!
Be wrong but be BOLD
Summarizing and telling your peers about your changes can be scary - especially if you're wrong. But remember, we're all on the same team! PR descriptions can be good indicators for managers and peers to re-visit a problem that may have been communicated ineffectively or not needed!
Give everyone the same odds
Writing a good summary for your reviewers opens the door for reviewers who haven't been working in the same trench as you. Everyone has different knowledge about the project, and more importantly, about programming. When our teammates understand our reasoning, we're enabling people who previously felt uninformed to ask questions or give alternative ways of writing the code. A good summary welcomes involvement from other people.
Wrong or right, your code matters. The way you communicate why you wrote that code will level you up as a programmer and as an important part of the team!
How to write a good PR description
Now that we have explained to you how important writing a PR description is, let's talk about how to write them. PR descriptions can boil down to asking yourself a few questions as you go line by line through your code diff (personally, I like to do this in the PR draft format so that I can copy links to files or make inline comments when relevant).
For the sake of a tangible demo, let's imagine we're submitting a new feature for a sign-up form in a sparkling new greenfield app. The below will be in our imaginary PR:
- Sign-up form + related input elements to be reused
- Underlying API call to an already set up service
We will start at the top of our imaginary diff and go through a few questions; you might recognize these questions from your grade school essay writing process.
Question #1: WHO
Who does this PR affect?
People who could be affected by a PR should be aware of the changes being made. This includes anyone who's waiting on changes to continue their own work, or leadership if they need to be informed of progress. It could also include your fellow developers if it changes how they'll need to interact with something or unblocks their own work.
We may also want to mention any newly-introduced utils that could be of value to other team members. It can also be helpful to "call people out" in a PR if you're fixing a bug that your PM has been very aware of and sad about, but nobody has had time to fix. A few new brownie points are always nice.
- Our PR qualifies for a few of these things: we're adding the UI that's connecting the authentication gateway to the app. No more free-for-all testing. So we'll specify that the team can now log in with their known credentials. We also have a date of birth custom validation util for our sign-up form that we should call out here.
Question #2: WHAT
What is this PR for? What does the code do? What is left?
This is probably the chunk that you're already addressing, to some degree. What we mean is simply describe what you wrote. Tell your reviewers what imports, modules, etc are referenced in context of your changes. Here is where we tell the story of what's going on in our PR.
If you have more than one feature change, addition or update to your code, separate the different sections as you write them up so that the content is grouped by context. By doing this, we're telling our reviewers what they are looking at instead of forcing them to infer.
- Our PR got kinda big (it happens). So the groups we'll talk about are 1) the sign-up form 2) the API.
We should also mention what our PR is not by admitting any lingering todos. If you have any type of undone work, list it out in your description, so your reviewers are aware before they go looking into your code. This can help prevent comments such as "Error handling isn't visible" in review if the reviewers know that "error handling" will be handled later. We like to use markdown to write checkboxes for these todo items! We also recommend writing subtasks or new stories (if that's your jam) and reference those tickets in your list for added visibility.
Question #3: WHEN & WHERE
When does this code run? Where in the app is the code?
Spell out when your code is used and what happens before and after it runs. It may not be obvious for someone who hasn't lived in your branch for the last 4 days.
- Our sign-up form is interacted with when the user navigates to www.myappname.com/signup, we'll want to give our reviewers reproduce-able steps to reach our code. We should also tell the reviewer what to expect after they sign in.
This is great for your reviewers to know as they pull your code and run it locally. Having context spelled out gives the reviewers clarity in what they are looking at, particularly in the event that the reviewers feel something weird is happening.
Hopefully this allows them to give more helpful feedback to you if something isn't working quite right, instead of leaving one comment on the PR specifying that "it's broken" and that it "needs work" before logging off for the night - now, it's tomorrow and you have to ask them what broke. Nobody enjoys this process.
Set the example for your reviewers by giving them context and they'll more likely return that respect by telling you where your code is going south. This enables you to debug with confidence or simply remind them to try again and this time run
Question #4: WHY
Why is this PR necessary? Why did the version change?
No need to get philosophical here, really just specify why you did what you did. If you have a story you're working off of it's good to reference that here, or copy out the description of the task so that your reviewers have quick reference material. Most of the time, I use this question to format an initial overview at the top of my description. It should be succinct and offer just enough context for your more detailed subsections to make sense.
- For our PR, we'll reference our Jira ticket number and say that we're adding the sign-up component and functionality that enables authenticate in to our app.
Now is also a good time to specify any package additions or version bumps. Bringing up these changes (and linking to the change log for that package) allows you to make sure your reviewers pay closer attention to these changes and help ensure nothing historical is going to break with the updates.
Question #5: HOW
How do I test this PR? How do I use it?
Here is where we write up step-by-step directions on testing our handy work for our kind reviewers. PR reviews take a long time, don't waste that time by having your reviewers poke around trying to figure out how to test your code!
Go through the process of demoing your code changes starting from wherever you expect your reviewers to begin. Write a list with each of those steps and what should happen at every turn. This might seem excessive, however it gives everyone clarity when reviewing. When writing this list you'll be surprised at how many small mistakes you'll catch before asking for new eyes on your branch.
This step-by-step reference is also useful for when your code is merged and you are submitting the story to QA. You can now copy those steps from your PR description and put them in your ticket so that QA has reproduce-able steps. This saves the time they would otherwise spend trying to figure out how to test the changes.
- For our PR, we'd document the steps of going through sign-up and what network stuff to watch for in our API request.
Putting it all together
So that seems like a lot, but really once you get into the habit, it's pretty straight forward. If we take our example from earlier about our sign-up form, our full description for that PR would look like the following:
# Overview Reference Story #AA-145 Adding the sign up ui component and functionality to allow authentication on our app. ## Updates The signup form is interacted with when the user lands on /signup. After the user signs in, `goToHome()` is called from routes.js, this sends the user to their homepage. ### Update part 1: Sign up form - New UI components for the sign up form needed to be made. - I have used formik for form state management. - New text input component in `Components/Input` - this will serve as a good base for future form functionality. - Created new util for custom date of birth validation. - Checked with @bruce for logic - @karen made a new ticket to move this logic to the backend. - For now, we need to handle it in the front end. ### Update part 2: Hooking up sign up functionality with API - Wired up submit on sign up to API. - It expects a valid email, name and date of birth. - Errors are not getting handled yet, - (but 200s are coming through consistently) ## How To Test - Pull branch, - run `npm install && npm run dev` - go to `[localhost:3000/sign-up](http://localhost:3000/sign-up)` - Enter dummy account data - (you're signing up so you don't need previous credentials) - Enter a DOB that's before June 1, 1995 - Open dev tools network tab - Submit data - See that /sign-up-submit was called in the network tab - And that it has your inputted data as the body of the request - When that request is finished: - you should see the page get redirected to localhost:3000/dashboard ## Demo or screen shots ## Remaining work - [ ] Handle return users with a login option (Story ##AA-146) - [ ] Handle errors for bad sign up attempts (Story ##AA-147) - [ ] Bypass login for already logged in users (Story #AA-159) ## Other notes - Added formik to dependencies for form usage - Once this PR is merged we will have to authenticate in order to reach internal views. Because of this, it's crucial Susan (@susiesue123)'s pr to bypass login #AA-159 get fast followed.
Go forth and write beautiful and helpful descriptions! Here are some tools to help you as you start on this journey.
Set up a PR template in your codebase
This guide assumes that your code is hosted on github. Other source control services may diverge from this slightly, so check their documentation to see what's different!
- Make a
./githubfolder at the root of your project. If it already exists, good for you! No extra work needed here.
- Add a file called
./githubfolder. The name of this file matters!
- Once you have filled in your pull request template, commit the changes and push it up to github. The pull request template should be visible in the github text editor when you open a new pull request.
If you're more of a website person, check out this blog post with instructions on how to add it straight from github.com!
And if you need some inspiration for how to format your new template, take a look at this resource for some examples.
Download and use a screen recorder for demoing changes
We like Giphy Capture, but pick whatever you are comfortable with. Whatever it is, use it to record your screen and demo what your PR should be changing or showing. This is so useful for demonstrating actions and features to reviewers.
Refresh your markdown skills
- PR descriptions are written in markdown. Organize your thoughts better by harnessing all that markdown has to offer us. We end up coming back to this classic cheat sheet.
There you have it
That's how we write our PR descriptions. There's more than one way to tie your shoes, and we'd love to hear from you what your go-tos are for writing descriptions.
In case this is an area of the pull request process you typically skip, try pausing and writing out a summary before you smash that 'Create Pull Request' button! Your team and your future self will thank you for taking the time to write a PR description