I have a project with hundreds of commits. It is a fork of another open-source project. At the time the fork was created, the git history was wiped. Now I want to reattach the history.
The original project has thousands of commits, call them: A <- B <- C <- D
Meanwhile, our fork has: E <- F <- G <- H
The branches do not share any common ancestors, but commit D
and E
have exactly the same filesystem. When E
was created, the git history was wiped.
How can I reattach them without solving merge conflicts?
Solutions I've tried:
git cherry-pick fork/initial..fork/develop
- I tried cherry-picking changes from the fork onto the original repo, but this resulted in merge conflicts. This solution tries to replay the commits linearly, but with all of the branching and merges that happened, there are merge conflicts all along the way.git rebase -i fork/initial fork/develop~0 --onto new-branch
- Rebasing instead of cherry-picking unfortunately has the same problem as above. It tries to replay the commits in order, leading to merge conflicts. I also tried with--rebase-merges
to no avail.git merge fork/develop --allow-unrelated-histories
-- This is the closest to what I want. It still resulted in a ton of merge conflicts (for reasons I don't understand?) but I resolved them all at once withgit checkout fork/develop -- .
andgit commit
. The problem with this solution is the "initial commit" of the fork branch is still the oldest commit to touch every file, so I am not getting any of the benefits of consolidating these branches.
All the solutions I’ve encountered so far require me to resolve conflicts. This should not be required, since I am trying to attach histories at a point where the filesystems are identical.
I just want to reattach the history to where it came from. Any ideas?
CodePudding user response:
You can try this
git rebase --onto D E H
That should put F, G and H on top of D.... well, not exactly. Those would be replicas of the original revisions, of course. That is, assuming E..H is a straight line.
Update
I have created a script that replicates history of branches on top of another revision without actually doing any cherry-picking like what rebase does. It creates new revisions on the fly using the information from the original revisions. Merges included, of course.
https://github.com/eantoranz/git/blob/replay/contrib/replay
Use it standalone, so, if you wanted to do something like git rebase --the-real-deal --onto new-base old-base tip
, you would do: ./replay new-base old-base tip
. From the example given in the question: ./replay D E H
. The single line it prints in stdout is the ID of the equivalent revision for the tip
of what you asked to replay.