Question

I want to pull in newer commits from master into topic, but not in such a way that topic changes are replayed over top of master, but rather vice versa. I want the new changes from master to be played on top of topic, and the result to be installed as the new topic head.

I can get exactly the right object if I rebase master to topic, the only problem being that the object is installed as the new head of master rather than topic.

Is there some nice way to do this without manually shuffling around temporary head pointers?

Edit:

Here is how it can be achieved using a temporary branch head, but it's clumsy:

git checkout master
git checkout -b temp   # temp points to master
git rebase topic       # topic is brought into temp, temp changes played on top

Now we have the object we want, and it's pointed at by temp.

git checkout topic
git reset --hard temp

Now topic has it; and all that is left is to tidy up by deleting temp:

git branch -d temp

Another way is to to do away with temp and just rebase master, and then reset topic to master. Finally, reset master back to what it was by pulling its old head from the reflog, or a cut-and-paste buffer. This gets it down to six steps, still awkward:

git checkout master
git rebase topic  # solve conflicts, git rebase --continue, if necessary
git checkout topic
git reset --hard master  # topic and master same now
git checkout master
git reset --hard HEAD@{13}

It is better to rely on some saved commit hash in the last step than to go hunting through the reflog.

Why this is useful

Suppose you have some people working on branch, who are collaborating on some development which is isolated from master, but stays integrated with it on a regular basis. By doing the rebase this way, we can avoid non-fast-forward changes on the branch (rewriting the branch history). How master is treated when it comes time to integrate the branch into it is another story; but there are options, including scenarios that avoid non-fast-forward manipulation of master.

Was it helpful?

Solution

So you have, e.g.:

A - B - C - D - E    <-- master
          \
            F - G    <-- topic

and you want:

A - B - C - D - E             <-- master
          \
            F - G - D' - E'   <-- topic

where D' and E' are copies of D and E? (I'm not at all sure this is what you want; it would help a lot if you draw a graph of what-you-have vs what-you-want.)

The simple way to do this is with git cherry-pick. While on topic, cherry-pick everything new on master—commits D and E above, but easily obtained programmatically:

git cherry-pick topic..master

OTHER TIPS

May be I'm misunderstanding what you're asking, but have you tried git merge master --squash and then git commit? This should move the latest state of master into topic with an additional squash commit to specify that the merge took place to get it into the state you're looking for.

This might not be exactly the way you want to mod your commit graph, though.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top