Search code examples
gitgit-merge

Git: How to make a merge commit with an arbitrary known end-state


For reasons, I need to restructure the (local) history of some commits including a merge commit. And I'd rather not repeat the merge conflict resolution process.

I already have a commit that represents the state that the final merge commit state should look like, and I'd like to set up the 2 parent commits and then tell git:

Look, just trust me ... there should be a commit with merge parents A and B, but where the codebase looks like C ... so don't worry about attempting to actually merge A and B together.

If I were rebasing I would know how to do this, with history manipulations, but I don't know how to do that when the history includes commits with multiple parents.


Solution

  • That is what git commit-tree can do. Suppose the final tree of the merge commit you want is on commit X, and the parents of the desired new commit are P1 and P2, then this can be done:

    git commit-tree -p P1 -p P2 -m "Some comment" X^{tree}
    

    That will print the ID of a commit that has P1 and P2 as parents (in that order) and the tree just like X. Feel free to check it out, git log it and, when you are sure that is what you like, place a branch on it.

    If you feel more comfortable without the hackish stuff, you could try to run the merge, which will lead to n conflicts.... and then use git restore --worktree --staged --source=X -- . which should work just as beautifully in getting the final tree you wish ready for you to wrap up the merge.