Let’s say you’re working on a big feature that you’re dark launching in little incremental Pull Requests. Every few days or so, you launch a new piece of this as you get it written. We’ll assume you have some sort of developer review process, and that it takes a few hours at minimum for this review process to get completed. We’ll also assume that you prefer to only merge code in the morning, so that you have all day to address any issues that might arise with its deployment.

Pretty soon you’ll find yourself in a situation where your current Pull Request is getting too large, but you’re in zen mode and you don’t want to stop development while you get your PR reviewed, merged, and a new one started. How can you fix this?

The easiest answer is to create a new branch based off your current branch. Let’s see what this would look like.

$ git branch
* master
$ git checkout -b MC/feature-x-part-1
# do some work, to the point where MC/feature-1 is big enough for a dev review, then:
git add .
git commit -m "This is a 500 line diff PR! "
git push
# create a pull request on GitHub to merge MC/feature-x-part-1 into master, then:
git checkout -b MC/feature-x-part-2
# do some work, then:
git add .
git commit -m "Part 2"
git push
# create a pull request on GitHub to merge MC/feature-x-part-2 into MC/feature-x-part-1

Now you can continue development on MC/feature-x-part-2 to your heart’s content while MC/feature-x-part-1 is in dev review. Once MC/feature-x-part-1 gets approved and merged into master, this is where the fun part begins.

First, if your sub branch (MC/feature-x-part-2) has a ton of commits in it, consider squashing them to save you time later (I’ll explain why in a minute). Only leave as many commit SHAs as you’re comfortable copying and pasting. Next, change the base branch of your Pull Request for MC/feature-x-part-2. Instead of having it set to merge into MC/feature-x-part-1, change it to merge into master.

Once you do this, you’ll see that all the commits that were associated with MC/feature-x-part-1 are now seemingly a part of MC/feature-x-part-2. You don’t want this; not only because it’s untidy, but because you can introduce grave errors in your code without realizing it. You want to get rid of these commits, but you can’t just rebase against master, in my experience (well, you can, but you’ll likely have a lot of needless conflicts that you’ll have to resolve). Instead, there’s a more elegant way to go about this: locally delete the sub branch (MC/feature-x-part-2), re-recreate it based directly from master, then cherry-pick the commits from the sub PR. Here’s what this would look like:

git checkout master
git branch -D MC/feature-x-part-2
git checkout -b MC/feature-x-part-2
# start in chronological order (i.e. oldest first) to cherry-pick the commits from your sub PR.
git cherry-pick 31c2e4a
# if any conflicts arise, then resolve them, then `git add .; git cherry-pick --continue`
# continue to cherry-pick all the commits in the sub PR
git cherry-pick fb690ed
git push -f origin MC/feature-x-part-2

This flow is swift, has no obvious downsides, and works well for me.