Consider the following scenario:
F1---F2----M1----F3 (feature)
/ /
C1-----C2----C3 (main)
I want to rebase the feature branch, so they appear as commits added after main, but not merge it yet. The problem is, main was already merged (not rebased) in the past and those commits are now in feature too. I want the rebase to automatically skip the commits already present in main and feature.
This is what I want:
F1---F2---F3 (feature)
/
C1---C2---C3 (main)
And afterwards just merge normally with a merge commit like so
F1---F2---F3 (feature)
/ \
C1---C2---C3-------------M1---F1'---F2'---F3' (main)
It's a bit like in this question, but I don't want to merge. Just rebase and then force push in the branch itself.
Git rebase, skip merge-commits
EDIT:
I found out that the scenario is way more complex.
Consider three branches, feature1(F) feature2(G) and main(C).
S stands for squash, M for merge commit.
Current situation
main C1--------------S1
\ /
feature1 F1---F2---F3
\ \
feature2 G1---G2---M1---G3---G4
I want to rebase feature2 onto main but skip all commits from feature1, since they are already in main (as a squash) and also in feature2 (merged commits)
The question contains tow different scenarios; for completeness I'll address both, but I'll start with the more recently added one, since I guess that's the one OP needs answered. So we have a picture like this:
I've changed the notation to reflect some things about how git works.
In OP's diagram,
main
containedS1
, with links toC1
andF3
. From context I understand that to be a "squash merge" ofF1
..F3
. But a squash merge is not really a merge; what makes it a "squash merge" is that it has no link back toF3
. So I've renamed itF123
to show what it contains, and removed the link.(Also this notation for branches better shows how they behave in git.)
So the question would be how to rebaes
feature2
and end withAnd now OP says
So that should give us something like
So when we
rebase
, we can use--onto
to separate the "upstream" (the boundary used to define what commits we rewrite) from the new base commit. In this caseThis rebases
feature2
but makesfeature1
the upstream; so we rewrite commits infeature2
but not infeature1
(and basically we always skip the merge commits themselves), so that gives usG1
,G2
,G3
, andG4
.But
onto
says "even thoughfeature1
is the upstream, I want to base the rewritten commits frommain
.There may be conflicts since the patches are not necessarily going to apply cleanly.
The original question (still shown above as of the time I'm writing this) was a simpler case
Note that in this case,
rebase
will simply do what's intended(Again there may be conflicts.)