I'm working on a project where the master branch is protected.
Usual workflow: Always create feature branches off master
and then send PRs. Once that has been merged into origin/master
, I can pull it into my local master then create some more feature branches off local/master
to work.
However I had a branch which was a quite important refactoring (update-deps-refactor
) and unless this is merged back to the origin master branch, I'm blocked doing other tasks (since I can't pull from origin/master
until it has been merged)
Can I just branch off update-deps-refactor
locally and continue to work? So when I send a PR for feature2
branch, the reviewer can merge at their own pace. Since update-deps-refactor
and feature2
will share some common commits, the git diff won't duplicate those commits again and the code reviewer also doesn't have to rereview the common commits between update-deps-refactor
and feature2
2 Answers 2
You can certainly branch off of any branch. If your refactor
branch is long-lived, and you need to add a new feature based off it the work you've already done, create feature2
off the refactor
branch.
However, those 2 branches are intertwined now. You'll need to regularly pull from refactor
into feature2
(in addition to pulling from main
into refactor
). Your PR from feature2
into refactor
will only reflect the diffs between those 2 branches, but when you open a PR from refactor
into main
you will get see diffs from feature2
as well - something to keep in mind for whoever is reviewing.
In order for the feature2
PR to be as clean as possible, the changes you make in feature2
should be completely unrelated to the changes you're making in refactor
. When you start changing the same functions in the same files on the two branches, that means conflicts. Given your use-case though (the feature depends on the work you're doing in the refactoring) this may be unavoidable.
Given all that, I'd caution about having such a long-lived branch (refactor
) that you are doing other development on (feature2
) at the same time. If this is truly a refactoring, adding in new features can complicate the determination that the refactoring was successful (is a bug due to the refactor or the new feature). So while it is possible to branch off of your refactoring branch, I'd evaluate whether you really want to do that, or focus on wrapping up the refactoring first.
-
Thanks. This is not a long lived branch. Also they don’t affect the same files either. I just wanted a way to continue working on a separate branch without having to wait for refactor to get merged. But I see your point. If the reviewer asks me to make changes in my refactor branch and then submit again, then my feature branch will have to rebase off refactor before I can continue working on the feature.rsn– rsn11/18/2022 19:42:22Commented Nov 18, 2022 at 19:42
-
I just wanted a way to continue working on a separate branch without having to wait for refactoring to get merged
well, everything you do is according to a planning. Both, the refactor and the following tasks are scheduled. they will be released at some point. Ask tech lead or PM when do they want the refactor to be released. That will tell you if you can branch offrefactor
or any other branch.Also they don’t affect the same files either
if both are changes absolutely unrelated, better branch offmaster
and give it a proper nameLaiv– Laiv01/18/2023 09:37:34Commented Jan 18, 2023 at 9:37
Use git rebase
to move the branches (refactor and feature) when work happens on the other branches (main and refactor) and finally when refactoring is merged. You can also move the commits from refactor that you need in feature to the base and first merge those into main rebasing refactor and feature on the merge of those changes.
Given new changes in refactor do:
git switch feature;
git rebase refactor...feature --onto refactor
Graphically you are doing. From:
* Refactor: new changes feature should be rebased on these
| * Feature
| * a commit in Feature
|/
* Fearure...Refactor (common base of Feature and Refactor)
* a commit in Refactor
* Main: before starting refactorring
To:
* Feature
* a commit in feature
* Refactor: new changes feature should be rebased on these
* this was the common base now it's just a commit
* a commit in Refactor
* Main: before starting refactoring
For changes in Main you rebase in two steps first Refactor onto Main then Feature onto the moved Refactor. Make sure to remember the hash of the base of feature (on create a tempoeary branch for it):
git branch tmp/feature-base feature...refactor;
git switch refactor;
git rebase refactor...main --onto main;
git switch feature;
git rebase tmp/feature-base --onto refactor;
git branch -D tmp/feature-base;
Graphically from:
* Main: new changes both branches should have these
| * Feature
| * a commit in Feature
| * tmp/feature-base, Refactor
| * a commit in Refactor
|/
* Refactor...Main: before starting refactoring
Intermediate:
* Refactor
* a commit in refactor
* Main: new changes both branches should have these
| * Feature
| * a commit in Feature
| * tmp/feature-base: this commit is no longer is the refactor branch but it is in the history of Feature
| * a commit in Refactor
|/
* before starting refactoring
To:
* Feature
* a commit in Feature
* Refactor
* a commit in refactor
* Main: new changes both branches should have these
* before starting refactoring
Once Refactor is merged into main rebase Feature onto the merge commit, this leads to a semi linear history with features visible and small commits that tell a story about why the code is as.
* Feature
* a commit on feature
* merge refactor into main
|\
| * Refactor
| * a commit in refactor
|/
* before starting refactoring
Don't be affraid of rebasing or merge conflicts.