How to handle pull requests in git and GitHub

What a pull request is in Git and GitHub, how pull requests work, and how data science teams can open, review, and merge them well.
data-science
git
python
Author

Federico Viscioletti

Published

March 30, 2024

A pull request is one of the most useful habits a data science team can build. It gives one person a structured way to propose a code change, and gives the rest of the team a structured way to review it before the change reaches the main branch.

Mastering pull requests in Git and GitHub is like learning diplomacy in coding. A good pull request proposes improvements clearly, welcomes feedback, and protects the codebase at the same time. This article explains what a pull request is, how it works in practice, and what both the author and reviewer can do to make the process useful instead of painful.

What is a pull request in Git?

A pull request is a request to merge changes from one branch into another branch. In a typical workflow, you create a branch, make changes, push that branch to a remote repository, and then open a pull request so teammates can review the work before it is merged into main.

Strictly speaking, pull requests are not a core Git command. Git gives you the branches, commits, pushes, pulls, diffs, and merges. Platforms such as GitHub, GitLab, Bitbucket, and Azure DevOps add the pull request interface on top: discussion threads, approvals, automated checks, code comments, and merge buttons.

So when people ask “what is a pull request in Git?”, they usually mean: what is the collaborative review step that happens after pushing a Git branch to a shared platform?

Pull request vs git pull

A pull request is easy to confuse with git pull, but they are different things:

  • git pull is a local command that downloads remote changes and merges them into your current branch.
  • A pull request is a review workflow used to propose that one branch should be merged into another branch.

The names are unfortunately close. Think of git pull as something you do on your machine, and a pull request as something your team discusses on GitHub or a similar platform.

How does a pull request work?

Here is the basic flow:

  1. Create a new branch from main.
  2. Make a focused change on that branch.
  3. Commit the change with a clear message.
  4. Push the branch to GitHub.
  5. Open a pull request from your branch into main.
  6. Ask for review from one or more teammates.
  7. Respond to comments and make any needed changes.
  8. Merge the pull request once the review and automated checks pass.

In commands, the first part often looks like this:

git checkout main
git pull
git checkout -b improve-model-evaluation
git add evaluation.py
git commit -m "Improve model evaluation report"
git push origin improve-model-evaluation

After that, you usually open GitHub in the browser and create the pull request from the pushed branch.

Why are pull requests important?

How skilled you should be at developing software is a hot topic for Data Scientists. In an ideal world, Data Science should be where software development, machine learning, and domain expertise meet (look at the fancy Venn Diagram). We all know that, as always, the reality is a bit more complex than what it looks like.

Data Science, the place where the unicorns live

That means we, as data scientists (yes, I am guilty too), are not always good at software development. We can lack the basics of what good software collaboration should look like.

Whenever we work on an analysis or a model on our own, we can indulge in adding and sharing all our work on the main branch. But, as soon as we start working in a team, this approach becomes inefficient or even harmful.

This happens when colleagues work on the same project. Usually, they end up editing the same scripts. We can use a powerful workflow that Git and GitHub offer together: pull requests. It creates order in what would otherwise become a spaghetti code club.

What a spaghetti code club looks like in my head, thanks DALL-E3!

If you need a wider Git refresher before going deeper into pull requests, see my guide to using Git for data science teamwork.

What should a pull request include?

A good pull request should make the reviewer’s job easy. At minimum, include:

  • a short title that says what changed
  • a short description of why the change matters
  • links to related issues, tickets, notebooks, or analysis
  • testing notes, including what you ran and what passed
  • screenshots, plots, or output examples when the change affects user-facing results
  • a clear request for the kind of feedback you want

For data science projects, this context matters even more. A small code change can affect metrics, model performance, business logic, or downstream reports. The pull request should explain not only the code change, but also the analytical reasoning behind it.

Best practices for pull request raisers

Start with a clear goal

Having a clear goal for each pull request is key. It helps reviewers understand the context, focus their attention, and decide whether the proposed change actually solves the intended problem. This clarity is particularly important when code changes involve data models, analytical algorithms, metrics, or business definitions.

By setting a clear objective, team members reduce the risk of scope creep or miscommunication. It also encourages meaningful feedback: instead of reviewing a mysterious bundle of files, reviewers can judge whether the change is correct, complete, and maintainable.

Include all the relevant information

Sometimes we are lazy (again, I’m guilty your honor). We want to finish a script we’ve worked on for weeks. So we create a pull request that only contains a title and nothing more. This is bad. We are not letting the reviewer understand the context of a change or its logic.

The best way to ensure that we have all the needed information is to use a template for each pull request. The template should contain the following points:

  • context: describe the changes made in simple terms

  • fully functioning code: does the code run without errors?

  • unit tests: did you test the code before raising the PR?

  • seek feedback: include any specific area where feedback is sought

Make smaller, incremental changes

Once I needed to review a PR where 84 files where changed. Whenever you end up raising such a big PR, consider how hard it is to review it. This is especially true for someone who lacks the context or didn’t work on the same project.

Reviewing something this big requires a considerable amount of time. Instead of taking a more agile approach, we can define the max number of files that one can change in a single PR. This will help the review process. It will enable faster integration and reduce the risk of big errors.

Use naming and organisation conventions

Following a consistent naming throughout the project and company is key. It’s important to ensure that everyone aligns on code standards. This practice helps maintain readability and understandability of the code changes.

Some examples of python code styles used in big tech companies:

Include Tests and Documentation

Ensuring the code runs without errors is crucial. It must also do what’s intended. This is another key part of a good codebase. A good pull request should have tested code. It should also have updated documentation. This ensures no surprises. The tests cover issues that might arise when the code runs.

For data science work, tests and documentation can take several forms:

  • unit tests for reusable functions
  • notebook outputs that prove the analysis still runs
  • updated README instructions
  • before-and-after metric comparisons
  • notes about data assumptions or changed feature definitions

Best Practices for Reviewers in Data Science

Approach with a Constructive Mindset

Constructive criticism delivered with a positive mindset can enhance the collaborative process. When a reviewer takes this view, they enable a more open and productive environment. Focus on suggesting improvements rather than pointing out flaws. This not only motivates the raiser but also fosters a sense of partnership. This philosophy also ensures continuous learning for both the reviewer and the raiser. Each interaction becomes an opportunity for their growth.

Understand the Context

Before reviewing code, you must understand the pull request’s context. This understanding forms the foundation for constructive feedback that aligns with project objectives. Reviewers should know the pull request’s goal. What issues does it address? How does it contribute to the project’s goals? Does it add features or improvements? How do they fit the current development cycle?

Taking time to understand the context goes beyond reading the code changes. Look at the related docs. Also, check the commit messages and any linked tickets or user stories. They can show the developer’s goals and the expected outcomes of the pull request.

Asking clarifying questions

So, the context or goal of the pull request is not clear from the provided information. Then, it’s essential to seek clarity.

  • Don’t hesitate to ask questions. If any aspect of the code or its purpose is not clear, ask for clarification. This can cover technical details. It explains the reason for specific choices. It also explains how the changes affect the codebase.

  • Use comments. Most version control platforms let you comment on pull requests. Use this feature to ask pointed questions. Use it for explanations of complex code parts.

  • Engage in a dialogue. Create a place where the raiser can explain without feeling defensive. Frame questions to help understanding.

Reviewers help by encouraging clear communication. They also understand the context of the changes. This ensures the review is thorough, fast, and leads to useful changes.

Focus on the big picture

The PR reviewers should focus on the big picture. They should consider how the changes fit into the project. They should consider the changes’ impact on existing functions. Not getting too bogged down in minor style issues is key. They don’t much affect the project’s goals and that is important. Following a style guide is important. But, in a project, we should welcome the small personal differences in coding styles.

Provide Clear, Actionable Feedback

The reviewer should also focus on giving clear feedback. The feedback should be something the raiser can use to improve the pull request. Using specific examples or suggesting alternative implementations helps clarify the feedback shared.

Foster a Culture of Learning and Improvement

The review process plays a key role in a Data Science team. It fosters a culture of learning and improvement in the team. The reviewer should always seek ways to encourage sharing. They should do this during the review process.

Example

I am a fan of explaining with examples. So, here’s an example of a well-crafted PR in a simple Python project. It adds a new feature: a function to calculate factorials. This example follows the best practices outlined in the article.

Title of the Pull Request

Add factorial function to math utilities

Description

## Overview
This pull request introduces a new function, `calculate_factorial`, to our collection of mathematical utility functions. The addition of this function aims to extend our utility module's capabilities, allowing it to support factorial calculations which are frequently required in combinatorial mathematics and algorithmic challenges.

## Changes Made
- Implemented `calculate_factorial` in `math_utils.py` which takes an integer input and returns its factorial.
- Added unit tests in `test_math_utils.py` to ensure the correctness of the factorial function across a range of inputs, including edge cases like 0 and 1.

## How to Test
1. Pull this branch into your local environment.
2. Run the unit tests using the command: `python -m unittest discover -s tests`.
3. All tests should pass, verifying the correct implementation of the factorial function.

## Related Issue
This PR addresses the feature request outlined in Issue #1234.

## Screenshots/Output Snippets
For a quick verification, here’s an example output of the function when input is 5:

>>> from math_utils import calculate_factorial
>>> calculate_factorial(5)
120

As always, I appreciate your feedback and am open to any suggestions or changes you think might improve this implementation. Thank you for considering this addition to our project!

Key Points in This Pull Request Example:

  • Title: The title is concise, clearly indicating what the PR aims to add without requiring the reader to dive into the details immediately.

  • Overview: Provides a summary of what this PR is about and the rationale behind it.

  • Changes Made: Lists the specific changes made in this PR, enhancing transparency and making it easier for reviewers to understand the scope of the PR.

  • How to Test: Includes clear testing steps, allowing reviewers to easily verify the functionality added or changed.

  • Related Issue: Links the PR to any related issue(s), providing context and ensuring it’s easy to track the development process.

  • Screenshots/Output Snippets: Offers a quick way to see the result of the change, aiding in the review process.

Common pull request questions

Is a pull request part of Git?

Not directly. Git is the version control system that manages commits, branches, and merges. Pull requests are usually provided by hosting platforms such as GitHub, GitLab, Bitbucket, or Azure DevOps. They use Git branches underneath, but the review interface is added by the platform.

What is the difference between a pull request and a merge request?

They are the same idea with different names. GitHub and Bitbucket usually say “pull request”; GitLab usually says “merge request”. In both cases, you are asking to merge one branch into another after review.

Who should review a pull request?

The best reviewer is someone who understands either the codebase, the business logic, or the analysis affected by the change. In data science teams, that might be another data scientist, an analytics engineer, a machine learning engineer, or a domain expert who can validate the assumptions.

How big should a pull request be?

As small as it can be while still solving one complete problem. A pull request that changes one model evaluation function is easier to review than one that changes the data pipeline, the model, the charts, and the documentation all at once. Small pull requests tend to be reviewed faster and merged with fewer surprises.

Conclusion: Harnessing the Collective Wisdom

  • A pull request is a structured request to merge one branch into another after review.

  • Pull requests are a catalyst for collaboration and knowledge sharing within data science teams. Following best practices can turn these requests into chances to grow and improve.

  • Improving how we handle pull requests makes the codebase strong and efficient. It also shows our expertise. This keeps our projects at the cutting edge. Every contributor drives them with diverse insights and careful work.

  • Embracing both raisers’ and reviewers’ views in pull requests enriches our understanding. It shows the collaborative journey in software development. It helps us appreciate it, leading to better, more resilient, and innovative solutions.

Share this article