I have a branch with commits that look like this:
A->B->C
A
and B
are merges from other branches which have not yet been merged to master
. C
contains the relevant changes to this feature branch.
C
is dependent on A
and B
. A
just got changed dramatically. However, these changes do not effect the parts of the code C
depends on. I would like to replace the merge from A
with a merge from the new A
.
In this case, the new changes are based on top of A
's old head. But I'd like to know how to do this in the case that new commits are not children of old ones.
Said another way, I constructed the branch by:
- Checking out
master
- Merging
A
- Merging
B
- Making changes and committing them as
C
.
I could create the branch I want now by doing exactly those things again (with the updated A
), but I'd like to be able to just replace the A
merge without reconstructing the branch.
CodePudding user response:
You could play a trick to try to avoid having to redo all the merges you have done (including A) but you will be rewriting history, there's no way to avoid it.
git checkout -b hack A # create a _hack_ branch where we will first get the _real_ contents of the new A, B and C
git merge new-A # merge "the new A" into hack
git merge B # merge B
git merge C # merge C
# this branch now has 3 commits that have _the contents_ of the _new_ A, B and C.... it's time to hack history to get this in
git commit-tree -p A~ -p the-new-A -m "The comment for the new A" hack~2^{tree} # create a replacement commit for A
# last command will print an ID, and we will use it in the next command
git commit-tree -p commit-id-from-previous-command -p B^2 -m "Comment for B" hack~^{tree} # create a replacement commit for B
# will print a commit id, will use it in next command
git commit-tree -p commit-id-from-previous-command -p C^2 -m "Comment for B" hack^{tree} # create a replacement commit for C
# again, we get a commit ID which should be the branch like what you wanted.
Do a git checkout, check the contents and also check its history (git log, gitk).... if you like it, then git branch -f master the-commit-id # or no commit ID if you did a checkout of it git checkout master
Of course, you have rewritten history which means that it has consequences so use with care.