문제

I have the following minimal example:

---M---A-----D1---D2---D3
   |\       /|
   | B1---B2 |
   \         / 
    -C1---C2-

Here,

  • M is master at the moment,
  • there are features
    • A,
    • B (consisting of B1, B2), and
    • C (consisting of C1, C2)

under development and on top of all those a feature

  • D (consisting of a series D1, D2, D3).

Now feature A was accepted to go into the master branch, therefore I have to rebase everything to A. This means, I want

---M---A-----------D1'---D2'---D3'
       |\         /|
       | B1'---B2' |
       \           / 
        -C1'---C2'-

Of course, it is easy to rebase B (B2) at A, and also C, alone/separately.

But how do I rebase my branch D (including B and C), keeping the merge D1 (as shown above)?

도움이 되었습니까?

해결책

You'll want to pass the flag --preserve-merges into your rebase command. This looks like:

git checkout D
git rebase A --preserve-merges

I'm far from an expert in the algorithm used by git to preserve merges, so I don't know what sort of conflicts you may or may not run into, but this will cause git to attempt to reconstruct your merge commit D1 during the rebase.

다른 팁

You could rebase branches B and C individually and then use grafts (or git-replace) to re-attach the new rebased branches to the merge commit. using grafts I would do

# rebase the individual branches
git rebase M B2 --onto A
git rebase M C2 --onto A
# replace old branch heads with rebased branch heads
echo $(git rev-parse D1) $(git rev-parse B2') $(git rev-parse C2') > .git/info/grafts

The grafts will make your git history appear as if D1 has parents B2' and C2'. If you remove .git/info/grafts, D1 will have its original parents again.

To make this permanent, use filter branch to rewrite your history:

#make it permanent
git filter-branch -f --tag-name-filter cat D1'

A more elaborate explanation can be found in this answer on prepending the past to a git repository. It also explains how you should use git replace instead of grafts. I gave the example with grafts because I have a bit more experience with those.

git replace would rather be along the lines:

# rebase the individual branches
git rebase M B2 --onto A
git rebase M C2 --onto A
# replace old branch heads with rebased branch heads
git replace B2 B2'
git replace C2 C2'
#make it permanent
git filter-branch -f --tag-name-filter cat D1'
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top