TL;DR: Use git rebase.
When developing a feature that is dependent on an unmerged branch, it is recommended to create your branch from that unmerged branch as the base branch while waiting for peer review. Once the dependent branch is merged, you can rebase your feature branch onto main. This workflow strategy is known as Stacked Branches.
For the first time, it might feel overwhelm. But trust me you will feel very happy after some reps and work seamlessly after.
Prerequisites
The first thing you need to get familiar is git rebase. Rebase is your friend to help you manage the branches.
You need to update your git config to use rebase instead of merge when pulling changes:
git config pull.rebase true
If you want to enable rebase for all repositories:
git config --global pull.rebase true
Git Rebase
I usually use git rebase with 2 cases. The first one is to rebase my branch onto main after the parent branch is merged. The second one is to update my branch with the latest changes from the parent branch.
Rebase child branch onto main after the parent branch is merged
The case:
- You have a branch
branch-athat is based onmainbranch. - Then you need to develop
feature-bthat is dependent on some feature inbranch-a. So you createbranch-bbased onbranch-a. - After peer review,
branch-ais merged tomain. - Now you need to rebase
branch-bontomain.
Branch before rebase
(main) ─── [OldCommit]
\
\
(branch-a) ─── [Method-1]
\
\
(branch-b) ─── [Method-2]
Expected branch commit after rebase
(main) ─── [OldCommit] ─── [Method-1]
\
\
(branch-b) ─── [Method-2]
Here’s how you can do it:
- First, make sure you have the latest changes from
main:
git switch main
git pull
- Switch to
branch-b - Run the following command:
git rebase --onto main branch-a branch-b
The above command basically saying: “Rebase branch-b onto main by removing the commits that are in branch-a but not in main.”
Update branch with the latest changes from the parent branch
The case:
- You have a branch
branch-athat is based onmainbranch. - Then you need to develop
feature-bthat is dependent on some feature inbranch-a. So you createbranch-bbased onbranch-a. - After peer review, you have to adjust and update the
branch-a. - Now you need to update
branch-bwith the latest changes frombranch-a.
Branch before rebase
(main) ─── [OldCommit]
\
\
(branch-a) ─── [Method-1] ─── [Method-1-updated]
\
\
(branch-b) ─── [Method-2]
Expected branch commit after rebase
(main) ─── [OldCommit]
\
\
(branch-a) ─── [Method-1] ─── [Method-1-updated]
\
\
(branch-b) ─── [Method-2]
In this case you can do following:
- Switch to
branch-b - Run the following command:
git rebase branch-a --update-refs
Push The Changes (after rebase)
If you have pushed the branch to origin, you will need to run push with --force-with-lease flag to force the change to the origin:
git push --force-with-lease origin branch-b
Why need to use --force-with-lease flag? Because the commit id will be different after rebase, and --force-with-lease flag will only overwrite the remote branch if there are no new commits on the remote branch that are not in your local branch. This can prevent data loss.