Branch A has a hot fix in PR under review. Branch B development is blocked by that fix (needed to continue development and/or compile).
As a background, the fix needed by branch B is in a different branch since it is independent fix not related specifically to feature in branch B but B depends on it.
The problem I can see is that if I cherry pick or merge the fix in branch A into branch B - I face potential issues down the road in case the review (and the fix) on branch A is rejected or changes are required. While branch B development assumed these changes as done and build on top of them.
One solution would be to stop development until the review on Branch A is complete and the fix merged into master. But that would delay development on branch B. Any other/better approach in this situation?
CodePudding user response:
To get latest changes from A
(on which B
is based - assuming as it is not mentioned in question) to B
is to use git rebase
. Git rebase will reapply B
commits on top of current A
tip.
3---4 branch B
/
1---2---fix branch A
will after git rebase A B
(which translates to two commands git checkout B
and then git rebase A
) become:
3'---4' branch B
/
1---2---fix branch A
As fixes PR might be adding more commits in A
you can apply git rebase A B
again to reapply commits 3 and 4 on top of the latest tip of A
.
3'---4' branch B 3''---4'' branch B
/ -> /
1---2---fix---fix2 branch A 1---2---fix---fix2 branch A
etc.
Note '
and ''
in my diagrams. While contents of commits (changes to source code) will be same, the commits will be new commits (have different hashes) as how this works is git
saves B
commits to temporary area, resets the starting point of B
to current tip of A
and then reapplies previously saved commits (if there are any conflicts on the way you'll have to sort them) - which generates completely new history. So to push rebased B
to e.g. Github you will need to use --force option to completely rewrite branch history.
See the official manual page I linked in top of my answer for more complicated scenarios (e.g. having some commits of B already integrated to A on the way). If you want to rebase not on A
tip but specific point in its history see option --onto
.
I recommend making backup of your current working tree first, before you experiment with rebase.
CodePudding user response:
Assuming your branch is linear and doesn't have any new merge commits on it, then I agree with blami's answer. The only tweak I would make is I would always use the fancy rebase version with the --onto
flag. In this way you don't need to care about whether A is simply updated with more commits (where regular rebase would work), or if A is re-written (where fancy rebase is needed).
For example, if you have 2 new linear commits on branch_b
, you can just use this:
git fetch
git rebase branch_b~2 branch_b --onto origin/branch_a
This works in the general case, and you can do it now, and anytime branch_a
changes. Finally, when branch_a
is completed into master
, then you would rewrite your branch one last time like this:
git fetch
git rebase branch_b~2 branch_b --onto origin/master
After that you can go back to using regular rebase until you complete branch_b
into master
:
git fetch
git rebase origin/master branch_b
Note with a regular rebase you can leave off the last argument of branch_b
if it's already checked out.
Obviously, change the ~2
in all of the above commands to however many new commits are on branch_b
at the time you perform the rebase.
Side Note: using these advanced commands is easy once you get the hang of it, but it requires using the command line and having a good understanding of what you're doing. It may not be the case that everyone can easily follow this method and I wouldn't recommend asking a large number of users to do it regularly. This is the reason that force pushing shared branches is frowned upon, since it requires everyone to be informed about the state of the branches, and understand how to use these types of commands. Most of the time, I would actually just recommend waiting until feature A is complete before starting on feature B, to avoid requiring this complexity.