crosser
crosser

Reputation: 737

Git rebase upon a branch that has commits combined by another rebase

I am working on two features simultaneously, "feature1" being the basis for "feature2". I create two branches for them; when I work on feature1, I commit into "feature1" branch; when I work on feature2, I commit into "feature2" branch, and regularly rebase "feature2" on top of "feature1":

git checkout feature2
git rebase feature1
... work ...
git commit ...

So, at some moment, I have this structure:

feature1: A -> B -> C
feature2: A -> B -> C -> P -> Q -> R

At this point, I am done with feature1; I want to squash A, B and C into a single commit D , and rebase feature2 upon this new state of feature1:

feature1: D
feature2: D -> P' -> Q' -> R'

Simple-mindedy, I run interactive rebase on feature1, successfully squash A, B and C into D, and try to rebase feature2

git checkout feature2
git rebase feature1

Now, git pulls D into the feature2 branch and tries to reapply A, B, C, P, Q and R on top of it. Of course, the updates in A, B and C are already applied by D, so they result in merge conflicts.

I figured by trial and error that when a merge conflict is reported while A, B and C are being re-applied, I just need to run

git rebase --skip

and I end up with exactly the result I need. But, first, this is not obvious if you didn't already know, and second, makes it easy to overlook and skip a potential genuine merge conflict. The latter should be unlikely, but if it happens, it's rather bad because you lose the corresponding update for good.

So, my question is: is there a better way to rebase your branch upon a branch in which some commits where recently squashed into one?

Upvotes: 3

Views: 134

Answers (2)

Boyd Stephen Smith Jr.
Boyd Stephen Smith Jr.

Reputation: 3202

I like using the --onto option to rebase and the @n reflog commit naming to solve my problem here, which often arises when interacting with non-git VCSes, or pretty much any time you are several local branches that are interdependent but not published.

After your first rebase: (you are squashing commits, but it can be pretty much any rebase)

git rebase -i master feature1

Follow it up with a second rebase:

git rebase --onto feature1 feature1@1 feature2

OR ("long hand")

git checkout feature2
git rebase --onto feature1 feature1@1

Which says, take the commits in feature2 that aren't in the previous version of feature1 and replay them on top of the current version of feature1.

Upvotes: 2

user4815162342
user4815162342

Reputation: 155670

Since rebasing messes with git's idea of merge history, git cannot tell automatically what you're trying to do. Instead of dealing with the conflicts and issuing a rebase --skip for each unwanted commit, use git rebase -i feature1 as your final rebase command, and simply remove the unsquashed commits from the list.

Upvotes: 2

Related Questions