Software Engineers are constantly working with Pull Requests (PRs). Most organizations have now adopted them as a best practice to ensure code that is merged upstream passes quality checks and peer reviews. I want to share a couple tips around dealing with PRs when issues arise.
If your organization prefers to rebase their feature branches prior to merging them upstream, and your PR starts to have many commits, then you have probably suffered from rebase hell (when conflicts just seem to go on forever).
For example, let's say you branched off develop
with your feature
branch. Your branches have diverged and develop now has ten new commits, and your feature branch has 100 commits. You have tried rebasing, but you end up in an endless loop of conflicts.
The first thing you should do is enable reuse recorded resolution. This will cause Git to apply the same resolution when it finds the same conflict. To enable it by default for all your repos:
$ git config --global rerere.enabled 1
This can solve your issue, but if it doesn't you may just want to squash your commits before updating from develop
. You could use interactive rebase if you prefer to do everything in your terminal, however I have found that the easiest way to squash your branch to keep working on it is to use your git provider's squash feature.
Here are the steps:
- Find the parent commit of your feature branch
- Create a new feature branch off that commit
feature-squashing
- Create a PR from your
feature
branch tofeature-squashing
- Click the merge and squash button
You can now update feature-squashing
with develop
without ending up in rebase hell.
Invalid commits within your Pull Request
The other problem I've run into is when some commits from upstream somehow end up mixed with your feature branch. This typically happens when someone has done a bad merge/rebase. If you catch the problem right away, you can reset your branch to what it was prior to the merge using reflog if you've pushed or by resetting if you haven't:
$ git reset --hard origin/feature
Then try to merge/rebase again. However, if you have commits after the bad ones, then you will need to extract those commits. You could use interactive rebase for this, but I prefer to use cherry-pick. Let's assume you have five commits with a bad one in the middle: 1 2 3 4 5, with 3 being the bad one and 0 being the parent commit of the feature branch.
Create a new branch merge-fix
from the same parent branch. It can be the same parent commit, or a newer commit from that branch if you also want to update with upstream at the same time. The syntax for cherry-picking a range is:
$ git cherry-pick start..end
It is important to note that start is not inclusive while end is. To make things simpler I have decided to use a notation that will change both sides being inclusive. The ^
symbol refers to the parent of a commit, thus:
$ git checkout 0
$ git checkout -b merge-fix
$ git cherry-pick 1^..2
$ git cherry-pick 4^..5
You would then test your branch to make sure you haven't broken anything. You could force push this onto your previous broken branch, or just keep working off this one.