Thursday, July 4, 2024

How to Rebase a Long-Standing PR on GitHub: A Case Study with OpenSSL

Hello, fellow developers! I’m Mounir IDRASSI, and today I want to share an experience I had with an old pull request (PR) on the OpenSSL repository. This post will walk you through the steps I took to rebase my fork and resolve conflicts, ensuring that my contributions could finally be merged.

The Background

On January 17, 2021, I opened a PR titled “Allow MinGW build to use BCryptGenRandom like MSVC build [master]” on the OpenSSL GitHub repository. The PR aimed to improve the MinGW build by dynamically loading bcrypt.dll and calling BCryptGenRandom at runtime, similar to the MSVC ...

We use LoadLibraryA to load bcrypt.dll from Windows System32 directory and 
retrieve the function pointer to BCryptGenRandom in order to call it 
dynamically at runtime. We also use GetModuleHandleExA to pin bcrypt.dll 
in the process memory in order to replicate the previous behavior where 
bcrypt.dll was linked against explicitly at link time as dependency. This 
also protected from unexpected external unloading of bcrypt.dll.

Fixes #13878
Fixes #11757
        

However, as often happens with open-source projects, time passed, and the PR remained unmerged for over three years. On July 3, 2024, an OpenSSL maintainer requested that I rebase the PR to resolve conflicts:

Could you please rebase the PR to resolve conflicts?
        

The Problem

After more than three years, my PR had accumulated conflicts due to the numerous updates to the OpenSSL master branch. These conflicts needed to be resolved before my changes could be merged. The process of rebasing seemed daunting, but I documented the steps to help others facing a similar challenge.

The Solution: Step-by-Step Guide to Rebase Your PR

Here’s how you can rebase your forked repository and resolve conflicts, just as I did for my OpenSSL PR:

1. Clone Your Forked Repository

If you haven't already cloned your fork, start by doing so:

git clone https://github.com/yourusername/openssl.git
cd openssl

2. Add the Upstream Repository

Link your local repository to the original OpenSSL repository to fetch the latest changes:

git remote add upstream https://github.com/openssl/openssl.git

3. Fetch the Latest Changes from Upstream

Pull in the latest updates from the original repository:

git fetch upstream

4. Checkout Your PR Branch

Switch to the branch where you made the changes for the PR. In my case, it was the master branch:

git checkout master

5. Rebase Your Branch onto the Latest Upstream Master

Rebase your branch to incorporate the latest changes from the upstream repository:

git rebase upstream/master

During this step, you may encounter conflicts. Git will pause the rebase process and mark the conflicting files.

6. Resolve Conflicts

Open the conflicting files in your preferred text editor and look for conflict markers (<<<<<<<, =======, >>>>>>>). Manually resolve the conflicts by choosing the correct code to keep.

In my case, only the file providers/implementations/rands/seeding/rand_win.c was affected by the conflit so resolving them was easy.

After resolving the conflicts, stage the resolved files:

git add <resolved_file>

7. Continue the Rebase

After staging the resolved files, continue the rebase process:

git rebase --continue

Repeat the conflict resolution and rebase continuation steps until the rebase is complete.

8. Push the Rebases Branch to Your Fork

After successfully rebasing, push the changes to your GitHub fork. Use the --force option because you have rewritten the commit history:

git push origin master --force

The --force option is necessary as the history of your branch has changed due to the rebase.

Conclusion

By following these steps, I was able to resolve the conflicts in my PR and bring it up to date with the latest changes in the OpenSSL master branch. If you find yourself in a similar situation, I hope this guide helps you navigate the rebasing process smoothly.

Happy coding!

No comments: