Reputation: 45
I'm attempting to move commits from branch "feature" to a new branch, which is forked from an earlier commit than "feature".
Suppose my tree looks like this:
master A - B - C
\
feature D - E
I'd like to move my feature commits D and E to a new branch derived from commit A, so that my tree looks like this:
desired D - E
/
master A - B - C
\
feature D - E
I created branch "desired" from A and attempted to rebase commits in "feature" onto the tip of "desired", but doing so pulled in commits B and C. Why didn't this rebase work, and how can I move these commits?
Upvotes: 1
Views: 40
Reputation: 45659
Let's redraw the commit graph in a way that better represents git's data structures. You have
A - B - C <--(master)
\
D - E <--(feature)
Then you go back to A
and create the desired
branch, which gives you
A <--(desired)
\
B - C <--(master)
\
D - E <--(feature)
Now I assume you said
git rebsae desired feature
thinking that the feature
branch means "commits D
and E
". But a branch isn't a set of commits; it's a pointer to one commit (hence my rearrangement of the graph). In git commits are "reachable from refs"; there isn't a real concept of a commit being "on a branch" or "not on a branch" beyond that.
So what makes B
and C
different from D
and E
? They're all reachable from feature
; but B
and C
are also reachable from master
(which is why you don't think of them as being "on the feature
branch").
Which brings us to your first question: the rebase command didn't do what you want, because the rebase command as you issued it doesn't know or care about the master
ref. The upstream is desired
(from which A
is reachable) and the source branch is feature
(from which A
, B
, C
, D
, and E
are reachable). So the rebase rewrites desired..feature
- i.e. everything reachable from feature
but not reachable from desired
- and that includes B
and C
.
What you want is to make master
your upstream, so that the command will rewrite master..feature
(i.e. D
and E
only). That in turn means you want the new base to be something other than the upstream, which calls for the --onto
option
git rebase --onto desired master feature
yielding
D' - E' <--(feature)
/
A <--(desired)
\
B - C <--(master)
\
D - E
(I kept D
and E
in the picture to emphasize the reason for calling the new commits D'
and E'
. The original commits are not deleted; if they're reachable from refs other than feature
, those refs will still "see" the original commits. The feature
branch now reaches two new commits with identity distinct from the original D
and E
.)
Upvotes: 2