Once I was working on a big feature. Everything was going fine until I got carried away and started to commit everything in one branch instead of splitting to multiple smaller ones. As a result I ended up with a huge PR that no one was able to review properly.
Letβs see how can you avoid getting in that situation and what to do if you already did.
First of all β do some planning and break task in parts. This is the only way youβll be able to avoid creating this monstrosity of a pull request.
Then youβll have two options, with both of them you create small PRβs with gradual improvements:
- Merging PRβs to master early and often.
- Having a long running feature PR with small reviewable child PRβs.
The difference is what you are basing them off. In first case you base them on master
and in second you base them on a feature branch.
Merging Early And Often
This is the preferred option. You better have a good plan of what you are going to do though. You donβt want to end up creating meaningless pull requests with lonely components that donβt interact with anything. Like models that no one uses.
Do it as incremental improvements. In your first PR set the base structure and then gradually improve it by adding more components and upgrading the old ones.
Long Running Feature PR
Youβll have to rebase the base branch with master and then rebase itβs children as well.
This approach might require some cherry-picking between branches if youβll be working in parallel with someone else.
Donβt forget to do the housekeeping and creating small PRβs for every new feature or you are going to end up withβ¦
The Worst Case
It started as a long running feature PR approach. But then I kinda slacked off with the housekeeping and started to commit everything in one of the child PRs.
Eventually I ended up with a huge PR with 100+ commits and 1.5k lines of code.
This is a very bad situation. Even if someone would dare to review it, heβll be more likely to overlook something.
So if you found yourself in similar situation β you need to do something to this PR to make it reviewable. For example you canβ¦
Break It Into A Stack Of PRs
When searching for a solution I found this blog-post of Grayson Koonce where a he proposed to close the original PR, copy itβs changes to a new branch and then create a stack of dependent PRs with incremental changes one on top of another.
First step
First you want to create a new branch based on master
with all the changes from that huge PR unstaged.
$ git checkout master
$ git checkout -b stacked-pr-example-1 branch-of-that-huge-pr
$ git reset master
$ git status
Now youβll see all the changes that were introduced in that huge PR in uncommited state. You can start commiting the changes and making stacked PRs.
First Pull Request
Youβll have to use git add --patch
to add specific changes to a commit. I have a post about this command.
But if you have unstaged new files β git wonβt be able to add them this way. To fix it apply git add -N
or --intent-to-add
to a file you want to see in your commit. This will tell git to add file itself but not it contents. After that you will be able to add lines from that file easily.
At this point you might want to check how many changed lines youβve already added. Use git diff --staged --stat
for this.
Once youβve staged all the needed changes, stash everything else and verify that it still works.
$ git stash --include-untracked --keep-index
--keep-index
will make it stash only files that have not been added and --include-untracked
will allow it to stash untracked files as well.
Time to commit the changes and create the PR.
$ git commit -m "Make some change to x"
$ git push -u origin stacked-pr-example-1
There is a nice CLI tool hub that will allow us to create a PRs easier:
$ hub pull-request
It will open the default editor and youβll be able to add PR description.
Next Pull Requests
Now create the branch for your next PR and pop the stash back:
$ git checkout -b stacked-pr-example-2
$ git stash pop
Repeat the add
, stash
, commit
steps.
Now create new PR, but make sure to base it off of the previous branch with the -b flag:
hub pull-request -b stacked-pr-example-1
Repeat the process until the changes are packed into PRs.
After Youβve Got Your PRs Reviewed
Here Grayson gives an important tip to propagate additional commits via git merge
instead of git rebase
. This way youβll be able to resolve conflicts in multiple commits in one go.
$ git checkout stacked-pr-example-2
$ git commit -am "Addressed this feedback"
$ git commit -am "Addressed that feedback"
$ git push stacked-pr-example-2
$ git checkout stacked-pr-example-3
$ git merge stacked-pr-example-2 # integrate changes from stacked-pr-example-2
Now, after youβve applied all feedback and got you PRs approved β time to land the stack.
As Github supports updating the base branch since August 2016, you can merge your stack in any order.
Top comments (0)