Home > Back-end >  How can I restore the git history of a fork where the history was deleted?
How can I restore the git history of a fork where the history was deleted?

Time:04-10

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 with git checkout fork/develop -- . and git 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.

  •  Tags:  
  • git
  • Related