Search code examples
gitrebase

Merging split history in git


I have been toying with rebase a bit, trying to split and combine history as described here: https://git-scm.com/book/en/v2/Git-Tools-Replace

Here is my test repository with split history: https://github.com/defufna/split-history

Note that "initial commit" and "Added description" commits both point to the same tree. What I'm trying to do is merge these two histories (while maintaining merges). I used this:

git rebase --rebase-merges --onto history 94da9b0f

This works, but I'm getting a conflict at 084dae5. This is a merge that resolves modify/delete conflict, and it requires me to manually resolve this conflict.

I am doing this in preparation for much larger repo merge, where I will have to do something similar but with 50k commits, so I would like to avoid manual conflict resolution. I am aware that git replace could solve my problem, but I'm curious if it is possible to do it without replacement. I would also like to keep sha values of commits in history branch.

Edit:

So I've managed to do what I want, but I'm not sure how good this idea is. I've added -i to rebase, and when I got todo file, I've changed every

merge -C 9751be2 Merge # Merge

line into:

exec git checkout `git commit-tree '9751be2^{tree}' -p HEAD -p refs/rewritten/Merge -m Merge`

I'm basically telling git whenever it encounters a merge to reuse tree from original merge.

It works as expected (for now), but it's a lot slower. Is there a better way to do this?


Solution

  • Note that "initial commit"[94da] and "Added description"[c00e] commits both point to the same tree

    Is there a better way to do this?

    Much.

    git replace --graft 94da c00e^
    git filter-branch master
    

    and you're done.

    git rebase exists to re-apply changes onto different base content, producing snapshots with new content. You already have all the snapshots you want, you only need to rewire the ancestry. git replace --graft does it locally, allowing you to experiment casually. git filter-branch exists to bake in rewired ancestry while applying any super-easy content changes -- but you don't even have any of those. You just want to rewire the master history.