DEV Community

Cover image for How to keep small Pull Requests
Antoine Lehurt
Antoine Lehurt

Posted on • Originally published at kewah.com on

How to keep small Pull Requests

Photo by @jdubs on Usplash

Pull Requests (or PRs) are an essential part of team collaboration. It helps to catch issues, spread knowledge, and it brings confidence in our changes. When reviewing code, the reviewers also take responsibility for the changes that will be merged. So, when opening a PR, it’s important to share as much information as possible. It helps the reviewers to recreate the mental model we had when working on the task (Why we did that change? How we did it? Why we did it that way?). The key is to keep our PRs small and focused. It’s fine to have a PR with several commits, and it’s even an excellent way to share the flow of our thoughts and changes. But the changes have the be related to the same goal. When PRs are significant, it’s harder to spot bugs, design flaws and the reviewers might feel overwhelmed. The worse case would be to approve the change without paying attention to it, which would defeat the initial purpose of working with PRs.

In this article, we will go through different scenarios to split a PR into smaller chunks.

Scenario 1: clean history, but too many unrelated changes

Before opening our PR, we realize that we could move some commits into a different PR. For instance, we created a new helper function on the way, and it will help reviewers to pay more attention to it.

$ git log
## branch: new-feature
* 8ee70d7 Commit 3
* b6a5da4 Add new helper
* d3b11d2 Commit 1
Enter fullscreen mode Exit fullscreen mode

We will create a new branch from master and reuse the commit “Add new helper” using cherry-pick. And then create a PR for that new branch.

$ git log
## branch: new-feature

$ git checkout -b style-helper master
## branch: style-helper
$ git cherry-pick b6a5da4
$ git push origin
Enter fullscreen mode Exit fullscreen mode

We can now go on GitHub and open the pull request.

The last step is to push new-feature to GitHub, but when we open the pull request, we need to change the base branch and use style-helper branch. (On GitLab it’s called the “target branch”.) We can check the commit history on the GitHub interface and see that “Add new helper” is not part of it. After merging style-helper PR, we should not forget to change the base branch tomaster before merging new-feature.

Scenario 2: need to split some commits

This time, we have mixed different changes in the same commit. We still want to create a different PR for our style helper, so we need to split that commit into multiple commits.

$ git log
## branch: new-feature
* 8ee70d7 Commit 2
* d3b11d2 Commit 1 <-- commit we want to split
Enter fullscreen mode Exit fullscreen mode

The first step is to go back to “Commit 1” using rebase, and then we willreset that commit to split it using add --patch.

## branch: new-feature

git rebase -i d3b11d2^
Enter fullscreen mode Exit fullscreen mode

Vim, or the editor defined in your gitconfig, will open and we specify which commit we want to edit.

pick 8ee70d7 Commit 2
e d3b11d2 Commit 1
Enter fullscreen mode Exit fullscreen mode

We are now back at “Commit 1” and it’s now time to split it. We first need toreset the commit to put the change back in an unstaged state so we can later use add --patch.

$ git reset HEAD~
$ git add --patch
Enter fullscreen mode Exit fullscreen mode

We follow the prompt and decide which hunk we want to stage using yes, no or edit.

$ git commit -m "Split 1"
$ git add --patch
$ git commit -m "Split 2: style helper"
Enter fullscreen mode Exit fullscreen mode

We are now done with splitting the commit. We can complete the rebase.

$ git rebase --continue
$ git log
## branch: new-feature
* 8ee70d7 Commit 2
* 02dbeb3 Split 2: style helper
* cf4ca41 Split 1
Enter fullscreen mode Exit fullscreen mode

We are at a similar stage as the first scenario, and we will go through the same steps for opening the two PRs.

Scenario 3: it’s a mess, let’s rewrite history

Sometimes things don’t go according to plan, and we end up with a spaghetti Git history. The best, in that case, is to rewrite it.

The first step is to find from which commit we want to start fresh.

$ git log
## branch: new-feature
* 255e8d5 Stuff 4
* 5c3fa7e Stuff 3
* deea3e8 Stuff 2
* 10a2b4a Stuff 1 <-- from here

$ git reset 10a2b4a^
Enter fullscreen mode Exit fullscreen mode

Now everything is back to an unstaged state. We will commit the change we want to include in our first PR using add --patch. Then stash the rest to create a new branch and continue to commit from there and finally open our second PR.

## branch: new-feature

$ git add --patch
$ git commit -m "Commit 1"
$ git stash
$ git push origin
Enter fullscreen mode Exit fullscreen mode

We can open the first PR using master as base branch.

Next, we create a new branch for the second PR.

## branch: new-feature

$ git checkout -b pr-2
## branch: pr-2
$ git stash pop
$ git add --patch
$ git commit -m "Commit 2"
$ git stash
$ git push origin
Enter fullscreen mode Exit fullscreen mode

We can open the second PR using new-feature as base branch.

We repeat these steps until we don’t have anything left in the stage.

Conclusion

It might feel cumbersome to go through these steps, but I think it’s important to show empathy to the reviewers and put them in good condition.

These are the scenarios I have encountered to split a PR into smaller chunks, feel free to share a different way of doing.

Top comments (0)