Rebasing to change parent merge element

Suppose I have the following story, where the top line is the main branch, the bottom is the function branch that combines with the master at one point, and D just returns C (which means that the working directory is the same as in B and D )

 A---B---C---D master \ \ E---F---G feature 

I want to add C and its return D to the story before merging into F , for example:

 A---B---C---D master \ \ E-----------F'--G' feature 

I don’t want to change E (this is actually a long series of commits).

git rebase --onto DB (as suggested here ) leads to merge conflicts (with or without --preserve-merges ).

Is there a way to accomplish what I want?

+6
source share
1 answer

Most methods will be somewhat painful. There's a moderately painless version using git filter-branch , except that the filter branch itself is painful. :-) (You have to filter the commit F and G and write a commit filter that replaces the new parents you want for F' , and allow filter branching operations to replace the original word for G )

I think the simplest method that does not resort to low level commands is to simply create a new merge and then rebase G to the new merge. The new merge may have conflicts, but we don't care, we just want to take the old merge tree, which we can do as follows:

 $ git checkout <sha1> # Use D or E sha-1 here. # Note: whichever you use will # be the first parent of our new # merge; choose based on that. $ git merge --no-commit <sha1> # use the remaining sha-1 here [ignore resulting stuff] $ git rm -rf . # Note: assumes you're in top dir of work tree $ git checkout <sha1-of-F> -- . $ git commit # Create merge commit F' 

In the first checkout you will be taken to a separate HEAD with one SHA-1, merge --no-commit will start the merge process with another SHA-1, git rm -rf . throws the merged tree and any conflicts, and git checkout <id> -- . fills the index and the work tree from the previous merge. The final git commit creates a F' merge with the same tree as the F merge, but with different parents.

At this point (still with HEAD disconnected) you can reinstall (or cherry) commit G (or many commits G ), and then force your branch to indicate the tip of the new graph. I would suggest using git rebase ... --onto HEAD , but I have not tested this with HEAD disconnected and there is at least one of the ways this might go wrong (allowing HEAD on the identifier is too late).

The low level git commit-tree command can be even simpler. Andrew C wrote the correct command in a comment , although you need to specify the branch name git update-ref . [Edit: maybe not quite right, the two parents you want are D and E , not D and B Again, first put the one you want as the first parent.]

The advantage (?) Of using more familiar commands is that, well, they are more familiar.

+8
source

Source: https://habr.com/ru/post/982644/


All Articles