Secret ingredients to quality software

  • Services
    • Products
      • Training
        • User Group
          • Rules
            • About Us
              • SSW TV
              SSW Foursquare

              Rules to Better Pull Requests - 15 Rules

              Pull Requests are the backbone of an effective development team. That's why it's crucial to ensure that everyone on the team understands the expectations around Pull Requests.

              1. Do you enable pull requests to ensure code is reviewed?

                Everybody strives to be perfect, but mistakes are normal, and it is easy for a developer to skim over errors when they've read their own code code hundreds of times!

                Pull requests are the best way to ensure that two sets of eyes see every change - so the responsibility is never solely on the person writing the code.

                When Pull Requests are enabled, developers must create a branch and make their changes on that branch. Then they submit a Pull Request to merge their changes back into main. Each pull request must be approved by another reviewer.

                i will not write bad code
                Figure: Bad example - Leaving the responsibility to each person to write perfect code

                pull request diagram
                Figure: Good example - Make Pull Requests required

                github pullrequest 2
                Figure: Pull requests also give version history for rejected code!

                Useful resources - learn about Pull Requests

                Video: What is a Pull Request? (3 min)

              2. Do you know how to write a great Pull Request (PR)?

                As a software developer, you are going to create Pull Requests (PRs) that you want to be easy for others to review and approve. The quality of a Pull Request can vary - from cryptic to well-written.

                Including a little bit of context helps your reviewer understand changes quickly so they can review your PR faster and give better suggestions.

                There are 2 easy things you can do to improve your Pull Request:

                1. Write a concise and self-explanatory title

                The key to writing a concise Pull Request is to base the PR itself on a PBI / issue.

                Good titles cover:

                a. What the Pull Request will do

                b. How the Pull Request achieved it

                c. Emojis! Follow the GitMoji.dev standard

                Examples:

                PBI title: Product Backlog Item 100359: "Desktop App | Exporting occasionally failed"

                Pull Request title: Fix exporting

                Bad example - Pull Request title does not tell what issues have been fixed and how

                Pull Request title: 🐛 BUG - Fix desktop app exporting - prevent database concurrent access while exporting

                Good example - Pull Request title briefly describes the fix that it has

                Having the "What" information allows the reviewers to quickly understand what this is about while having the "How" can help the reviewer to quickly understand how your PR solved the problem. Sometimes we might want to put the "How" in the PR body if it is too long or hard to explain in one sentence.

                2. Write a clear and concise description

                The Pull Request description is a medium for the developer to tell the reviewers what the changes are about.

                Tip: For straight-forward changes the self-explanatory title might be enough. You should still include context so the reviewer knows what initiated the changes (examples below)

                Good descriptions cover:

                a. Context:

                Linking the source to a PR serves as documentation on which development work that was done. It helps in the future to debug when and which changes were introduced and the original specification of that piece of work.

                Tip: If you noticed that a change needed to be made and had no specific task/issue, use 'I noticed...' from above.

                b. Did you do pair or mob programming?

                c. What the PR is about and why you raised it

                d. How the PR will achieve the feature / fix the bug / other goals

                e. Include a screenshot/GIF/Done Video to help the reviewer to understand the changes (e.g. styling changes)

                f. Tell he reviewers if there is an area you are uncertain about, e.g.: I'm looking for feedback on this code

                PR title: Update Rule “meaningful-pbi-titles/rule”

                PR description:\

                Figure: Bad example - Cannot tell what was done here

                PR title: Update Rule “meaningful-pbi-titles/rule”

                PR description: Changes made:

                1. Added missing video figure to embedded YouTube video
                2. Fixed typo:
                  From:
                  Use emojis. See our rule on emojis in Scrum).
                  To:
                  Use emojis. See our rule on emojis in Scrum

                Figure: OK example - What was done is clear, but both editor and reviewer may spend too much time on the description of such simple changes

                Try to make generic comments that objectively summarize your changes. This way the reviewer will know what to expect and confirm the changes by looking at the file diffs.

                PR title: Update Rule “meaningful-pbi-titles/rule”

                PR description: Added missing video caption + removed unnecessary brackets

                Figure: OK example - Clear and concise description, however it's not clear what task triggered the change

                PR title: Update Rule “meaningful-pbi-titles/rule”

                PR description: From email, subject: SSW.Rules - Video caption missing Added missing video caption + removed unnecessary brackets

                Figure: Good example - It's clear what changes are being made and where the task came from

                There is also well-known Pull Request semantics like Conventional Commits on how to write a PR body, but we can still have a great PR without using such preciseness.

                FAQs

                Q: Are you making many small changes?

                A: You should summarize by saying: “Improved readability” OR “Fixed typos and grammar”.

                Q: Are the changes big and complex?

                A: You should include a demonstration of the change.
                E.g. A screenshot to show text/UI changes, or a Done video to demo functionality changes.

                Q: Are you using a GUI editor (like Netlify or Tina)

                A: If you're using a GUI editor for your PRs, you may need to go to the PR afterward and update the description to include the context

                cms bad example
                Figure: Bad example - An automatically generated description doesn't give any context to reviewers

                cms good example
                Figure: Good example - Updating the PR description to follow the repository standard helps you provide context to reviewers

              3. Pull Request - Do you do over the shoulder reviews?

                An "over-the-shoulder" review is one of the best ways to avoid merge debt. When a pull request (PR) is ready to be reviewed, get someone with you either in-person or on call, and go through the PR together. This not only allows you to demo the content of the PR but also talk with the person taking feedback when needed.

                When you have finished coding, don't just create a PR and throw it over the fence. Part of finishing a PR is getting it approved.

                The best way to get it approved is via an "over the shoulder" review
                - Adam Cogan

                Drafting PRs

                A good way to avoid someone merging your PR before you have done an over the shoulder review is to keep the Pull Request in draft mode until you are ready for it to be reviewed for merging.

                Note: You should always avoid merge debt, it's your responsibility to follow up on your PRs and get them merged as soon as possible. For more info,

                See Do you avoid Merge Debt?

              4. Do you avoid Merge Debt?

                If you are in a team (i.e. an internal contributor), it is the PR author's responsibility to get a PR reviewed and action feedback ASAP.
                As an internal contributor it's a good idea to have a call with the PR reviewers.

                If you are not part of the team (i.e. an outside contributor), reviewing the PR is the responsibility of the repo maintainers. Actioning the feedback is still the responsibility of the PR author. As an outside contributor, it's a good idea to chase the reviewers by reaching out with a comment on GitHub, or through the repo's community (e.g. Discord channels).

                When a PR is created but left open for a long time, it becomes stale. Stale PRs equate to merge debt because the longer the PR stays open, the more changes occur on the main branch and the harder it is to merge back in.

                Merge debt refers to the amount of work a PR has to undergo before it can be merged into the main branch. If the PR is brand new, the amount of work required to merge is near to none, but as the PR stays open, the more work gets done on the main branch, leading to more work needing to be done to ensure the PR is up-to-date and able to be merged.

                Merge debt can be avoided by:

                • Ensuring PRs don't stay open for too long
                • Conducting daily reviews on repos to ensure all PRs that can be merged are merged
                • Ensuring that once a PR is ready to be merged, an "over-the-shoulder" review occurs.

                Figure: Bad example - Pressing commit and forgetting about it. PR has been left open for a over 2 weeks

                over the shoulder pr
                Figure: Good example - Devs reviewing a PR on a call - no merge debt!

              5. Do you use Pull Request templates to communicate expectations?

                Pull Request templates are a great way to communicate expectations to developers. You should can create different PR templates for different types of PRs. For example, you can have a PR template for bug fixes, a PR template for new features, and a PR template for refactoring. You are also able to create specific PR templates for specific code paths.

                You can read more about PR templates in the GitHub docs at Creating a pull request template for your repository

                When creating a PR template, think of how you can help developers create great PRs

                no pr template
                Figure: Bad example - There is no information to guide developers

                pr template with comments to guidance
                Figure: OK example - The PR template contains handy links to guidance for creating great PRs ⭐

                pr template asking for context
                Figure: Good example - This PR template asks for **context needed to review**, along with links to guidance for creating great PRs ⭐

                Tip: You can use comments in the markdown as above. These comments will not show when the PR is created, and is only visible when editing the description.

                For a great Pull Request template, take a look at @SSWConsulting/SSW.GitHub.Template

              6. Do You Know to not 'Push' your Pull Requests? (aka discuss then build)

                For the original article check out Don't "Push" Your Pull Requestsby Ilya Grigorik.

                Open source software projects love it when the community get involved and pitch in.

                It's great when someone fixes a bug.

                A short pull request to fix a small problem is easy to review and accept.

                It's great when someone adds a much-needed feature...as long as the feature fits in with the project the core contributors have for the project...and it meets the existing coding patterns and engineering standards.

                This is where frustration often starts to set in on open source projects.

                A contributor has a great idea for a feature, or identifies an area where they can add value and does so without consulting with the core contributors who have often spent hundreds of hours working on the project.

                Their contribution might solve their problem, but after it has been accepted it will most likely be left for the core contributors to maintain.

                # Poor Communication Contribution

                • developer has good idea for project
                • bashes away and writes 600 lines of code
                • submits pull request
                • core contributor looks at large pull request she doesn't fully understand purpose of request / the problem it solves she doesn't like that the PR author hasn't followed the existing coding standards she makes a push back comment

                Figure: Bad Example - Poor early communication can lead to mis-directed work and pull requests not being accepted

                # Good Communication Contribution

                • developer (PR Author) has good idea for project
                • reviews the list of outstanding issues for the project and confirms that someone hasn't already had the same idea and started a discussion on it
                • author creates an issue on GitHub and outlines the problem they are trying to solve, and outlines their suggested solution
                • the core contributors and other interested parties can help refine both the idea for the feature and the suggested implementation
                • the author can then start working on the feature knowing that their idea for the project complies with the maintainers vision for the project and know it is likely to be merged into the core codebase

                Figure: Good  Example - Good communication leads to collaboration and better outcomes for the author and the project

                # Projects with Internal Teams

                • Internal SSW team members should only work on features during work hours that have been assigned to a release by the core contributors for a project
                • Features will be assigned to a release during the Community Standup
              7. Do you know when to add your changes to an existing PR?

                Pull requests are a fundamental feature of collaborative software development, allowing contributors to propose changes to a project and receive feedback from other developers. When reviewing a pull request, it can be tempting to make additional changes beyond those requested by the PR creator.

                Certain projects (E.g. SSW.Rules) allow these additional edits, without the need for extra reviews by someone else. Knowing that, it's crucial to make sure the changes are correct, necessary and beneficial to the project before adding them.

                Most common scenarios where editing an existing PR is encouraged:

                • Fixing typos
                • Grammar improvements
                • Formatting (Markdown) fixes/improvements

                For the cases where your wanted change can serve as a learning opportunity to others, it is always best if you ask them to action by requesting a change. This way the extra change can be avoided in the future.

                Warning: Only experts should include their own changes to an existing PR.
                Never add extra changes to a PR if you are less experienced or unfamiliar with the project. The additional changes may be unnecessary or even harmful!

                Ultimately, the decision to add additional changes to a pull request should be made based on the needs of the project and the expertise of the contributors involved. It's important to carefully consider the impact of any additional changes and ensure that they are aligned with the project standards.

              8. Do you save failed experiments in abandoned pull requests?

                Assume you are creating a cool new feature. First you will create a new branch, create some commits, check it works, and submit a pull request. However, if you are not happy with the feature then don’t just delete the branch as normal. Instead, create a pull request anyway and set the status to Abandoned. Now, you can continue to delete your branch as normal.

                This makes sure that we have a historical log of work completed, and still keeps a clean repository.

                create pr for failed branch

                Good Example: Setup pull request for feature branch so that we have a history of the commits

                abandoned pr for branch

                Good Example: PR is abandoned with a deleted branch

              9. Do you know when you use @ mentions in a PBI?

                When the Product Owner verbally requests a change to a PBI, how do you update the PBI to reflect the change and also keep track of the conversation?

                You could send yourself a "To Myself" email and update the PBI description accordingly, but only those people included in the email chain are aware of the conversation. Only send a "To Myself" email when there is no Product Backlog that is related to the request, otherwise you should create or update a PBI and @ mention the Product Owner and other relevant people (@ mentioned people will still receive an email).

                bad mention pbi
                Figure: Bad Example – don't use emails to update tasks

                Instead, what you should do is use the discussions feature in the PBI and mention the user using "@<username>".The benefits of using comments are:

                • Quick and easy, no need to compose an email
                • History is visible to anyone looking at the PBI (with email, if you don’t cc them, they wouldn’t have a clue)
                • Easy to see all important notes/comments in one place instead of digging through email

                When someone (especially the PO) asks you to fix a PBI, mention that person in the PBI comments so they know when it’s fixed.

                Example: When replying to "Hey XXX, can you please fix PBI 123?"

                Bad example: "I have found the PBI and moved it near the top of our backlog"

                Good example: "I have found the PBI, prioritized it near the top, and @mentioned you so you know when it is fixed"

                Azure DevOps PBIs

                To create a new PBI in your Azure DevOps project:

                1. Navigate to Boards | + New Work Item and select the type that best suits your item
                2. Enter your PBI title
                3. @ mention your desired user in the description

                good mention pbi
                Figure: Good Example – Using @ mentions in Azure DevOps discussion

                good mention pbi 2
                Figure: Good Example – Email still gets sent to the users who are mentioned in the discussion, so they can still chime in if any details are incorrect

                It is also good practise to use @ mention in the discussion to track changes and request test pleases. Try formatting your mentions like an email to clarify both accountability and responsiblity and identify the current status of the project.

                pbi formatting mentions
                Figure: Good Example – Using "CC" and Greetings as you would in an email. Emojis are helpful too! 😊

                GitHub Issues

                MicrosoftTeams image
                Figure: Good Example – Using @ mentions in GitHub

                Tip: You can @mention on your pull requests as well.

              10. Do you avoid linking issues to PRs in GitHub?

                GitHub provides a way to link issues to PRs. This is useful to see what PRs are associated with what issues. However, when you make this link, the issue will close when the PR is merged.

                This is not a good idea because it can cause issues to be closed prematurely. This can lead to confusion and lost work.

                Issues should not be closed until all the tasks are complete and have a done comment as per Do you close PBIs with context?

                bad link issues prs
                Figure: Bad Example -

                Tip: Avoid using closing keywords e.g. "closes #123" or "fixes #123" in PR descriptions. This will automatically link the issue to the PR and close it on PR merge. Instead, use terms like "relates to #123" or "addresses #123" to link the issue to the PR without closing it.

                This was a feature GitHub added but it is not a good idea to use it, if you agree the behaviour should be changed, go upvote this discussion https://github.com/orgs/community/discussions/17308

              11. Do you merge open source pull requests using the squash and merge option?

                When you are working on an open source project, you will often get pull requests from contributors. When you merge these pull requests, you should use the squash and merge option. This will squash all the commits into one commit and then merge it into the target branch. This is a good practice because it keeps the commit history clean and easy to read. It also makes it easier for other developers to understand what changes were made in each pull request.

                Commit Message

                Like any commit message, the PR commit message should be short and descriptive. The easiest way to achieve this is to combine the PR title and commit details.

                confirm squash and merge with no details
                Figure: Bad example - This merge will be missing important information from the commit message

                confirm squash and merge
                Figure: Good example - This merge will include all the commit messages as part of the PR commit message

                In order to get GitHub to use your commit details by default you need to change the configuration for the repository.

                squash merge settings
                Figure: Repo Settings | Pull Requests | Allow squash merging, and change the value to **Default to pull request title and commit details**

                Limit merge types

                You should limit the merge types that are allowed on your repository. This makes it easy for everyone to know the expected merge type of the repository when the PR is merged.

                limit merge types
                Figure: Repo Settings | Pull Requests, Remove **Allow merge commits** and **Allow rebase merging** to force all PRs to be squash merged

                Automatically delete head branches

                After a branch is merged into the target branch, you'd not want to continue development on the previous branch as the changes were squashed in. It's always a good idea to create a new branch after a PR is merged from the target branch if you have additional changes. To make this easier, you can configure GitHub to automatically delete the branch after the PR is merged.

                automatically delete head branches
                Figure: Repo Settings | Pull Requests, Enable **Automatically delete head branches** to avoid stale branches

                Other configuration

                If you find that pull requests are often approved but for some reason not merged in, you may want to enable auto-merge. This will automatically merge the PR when all the required checks have passed.

                auto merge
                Figure: Repo Settings | Pull Requests, Enable **Allow auto-merge**

                You may want to enable Always suggest updating pull request branches, this can be done from Repo Settings | Pull Requests, this provides contributors with an easy way to update their branch from the target branch without performing the merge themselves on their local machine.

                update branch
                Figure: Providing contributors with an easy mechanism to update their branch helps reduce conflicts if they need to make more changes

              12. Do you have a standard set of pull request workflows?

                Getting started with a new repository can be daunting, especially if you are new to the project. Having a standard set of pull request workflows can help you get started and make sure you are following the same process as everyone else on the team.

                A few standard workflows helps developers see a consistent process across all repositories. This makes it easier for developers to get started with a new repository and makes it easier for developers to move between repositories as the feedback they get from each pull request is consistent.

                Below are a few standard workflows that you can use in your repositories.

                PR - t-shirt size the pr

                This workflow uses the microsoft/PR-Metrics action to update each pull request with information that helps ensure engineers keep PRs to an appropriate size with appropriate test coverage, while informing reviewers of the expected time commitment for a thorough review of the code.

                pr metrics
                Figure: PR Metrics gives warnings with suggested actions

                You can find the workflow at SSWConsulting/SSW.GitHub.Template/.github/workflows/pr-metrics.yml

                PR - Manage Stale PRs

                This workflow creates adds labels to pull requests as they age.

                pr age labels
                Figure: It's easy to see at a glance when PRs have been around for a while

                The workflow will also ping the author of the pull request after around 36 hours and remind them about merge debt

                pr merge debt reminder
                Figure: A gentle reminder helps remind developers the next day that their pull request needs attention

                You can find the workflow at SSWConsulting/SSW.GitHub.Template/.github/workflows/pr-manage-stale.yml

              13. Do you still review Pull Requests when you are not a required viewer?

                As a repository maintainer you would generally setup a branch policy which may include a certain number of reviewers before a pull request can be completed, this could also include that certain reviewers are required instead of this being wide open to just anybody. This is a great way to ensure that code is reviewed before it is merged into the main branch.

                However, this does not mean that you should not review pull requests that you are not required to review.

                Let's take a look at some of the benefits of reviewing pull requests, even if you are not a required reviewer.

                As a junior developer, you may not feel comfortable reviewing a senior developer's code, but you should. You may not be able to provide any feedback around standards and best practices, but you can ask questions. This is a great way to learn and understand why the senior developer did something a certain way.

                When you ask questions in a pull request, you are giving the author the opportunity to take a step back and think about what they have done and how they've done it, explain their thought process and potentially where you could learn more about the approach. Alternatively, you could point out a different way of achieving the same result which could be a better approach and they could change their PR.

                • ✅ You could learn something new
                • ✅ The author could learn something new
                • ✅ Congrats... you've just created some micro-documentation that may never have existed before

                The more people have approved a pull request, the more confidence you can have that more people in the team have looked at and agree that the code should be merged into the branch. This is effectively the same approach as getting a "Checked by xxx" on an email, see Do you use 'Checked by xxx'?.

                • ✅ Shows the team you understand and agree with the code changes
              14. Do you use Co-Creation Patterns?

                These days Pull Requests are the de facto standard for getting code reviewed. Once a developer has finished their change, they will typically submit a Pull Request and move on to their next task. This allows for an asynchronous process to take place which may seem like a good idea, but often is not and can also lead to inefficiencies.

                ❌ Problem - Inefficient Code Reviews

                Inefficient code reviews can be caused by:

                • Requesting feedback too late
                • Receiving feedback too slow
                • Creating large Pull Requests
                • Excessive context switching
                • Too much work in progress
                • Unclear feedback

                co creation 1
                Figure: Vicious cycle of being blocked and picking up yet another task (source: https://www.infoq.com/articles/co-creation-patterns-software-development)

                co creation 2
                Figure: Inefficiencies caused by asynchronous code reviews (source: https://www.infoq.com/articles/co-creation-patterns-software-development)

                ✅ How to Make Code Reviews More Efficient

                • Author - Do over the shoulder reviews
                • Author - Ask for feedback early before the PR, if you are uncertain that you're on the correct path
                • Limit work in progress

                  • Author - Make sure your Pull Requests are merged, before starting a new task
                  • Reviewer - Prioritize Pull Requests before starting a new task
                • Author - Create small Pull Requests

                  • This requires a smaller block of time to review which makes it easier for the reviewer to find the time
                  • Less risk - reduces the chance of an incorrect approach being taken
                  • Get quality feedback - small blocks of code are easier to digest
                • Reviewer - When reviewing asynchronously

                The Ultimate Solution - Co-Creation Patterns

                Small Pull Requests have many benefits as outlined above. However, each Pull Request comes with an overhead and making Pull Requests too small can introduce unnecessary waste and negatively affect the throughput of code. In order to not lose throughput with small PRs, reviewers need to react fasterThat leads us to synchronous, continuous code reviews and co-creation patterns

                So, with the async way of working, we’re forced to make a trade-off between losing quality (big PRs) and losing throughput (small PRs).

                We can avoid this by using co-creation patterns. As a general rule, Pull Requests with less than 20 lines of code, and larger changes with a degree of complexity/risk, make good candidates for co-creation.

                The idea is that you do small PR's but also limit WIP. If you create several small PR's quickly and are waiting for code reviews, you can become blocked very quickly. By co-creating, the small PR's get reviewed & merged instantly which avoids getting blocked and enables you to smash out loads of small PRs! 💪

                Daniel Mackay - SSW Solution Architect

                Patterns

                Co-creation patterns can take several forms:

                1. Pair-programming: starting, reviewing and finishing a change together
                2. Mob-programming: working in a small group, that collectively has all skills required

                Advantages of co-creation

                Co-creation allows us to have both quality and throughput by providing the following advantages:

                1. More context when reviewing
                2. Higher quality
                3. Faster communication
                4. Faster course correction
                5. Less delay - no waiting
                6. Eliminates context switching - working on a change together reduces WIP which further increases throughput
                7. Emotions are removed - instead of having an 'author' and 'critic', the code is created together.
              15. Do you have a page owner for each webpage?

                Managing webpages can be challenging, especially in projects with many contributors. When editing a page, a common problem is not knowing who the original author was. This is bad, because it's important not to change something that was there for a reason!

                The best way to solve this is by having a page owner for each webpage.

                Why?

                A designated page owner ensures someone is responsible for the accuracy of the page content. It avoids confusion about who to approach for major changes, and it allows the page owner to keep an eye on changes.

                Steps

                1. Markdown files - Add an 'owner' field in the frontmatter metadata for each page.
                2. New pages - The field should be required when creating a page.
                3. Pull requests - Automatically add the page owner as a reviewer for any pull requests that modify their page.

                Tip: this can be done automatically with a GitHub Action (or similar automation)

                ✅ The "owner" (person responsible) is aware of and can approve any changes

                ✅ People know who to consult about changes to the page

                🤔 We don't use CODEOWNERS for this because we don't want to block pull requests for minor edits

                ❌ When trying to work out who is the page owner, version history is not good enough - often the creator of a page is not the actual author e.g. a dev makes the page for a Marketing person

                no author bad
                Figure: Bad example - No owner field. Impossible to see who wrote this page!

                page owner good
                Figure: Good example - Frontmatter with an 'author' field.

              We open source. Powered by GitHub