Rebasing merged trees in Git

I have something akin to the following history (but more complicated with several merges):

        F - G - H - K - L - …
       /           /
      /       I - J - M - …
     /       /
A - B - C - D - E - …

A′- B′- C′- D′- E′

A and A′ are identical trees with different histories.

  • Ivy with Git Repository
  • I need to create another branch from a past commit
  • create an intermediary git repository
  • how to remove a file from github and stop being tracked?
  • Bitbucket server webhook to jenkins not posting after upgrade from stash
  • Android Studio Path to Git executable
  • I want to rebase all branch commits to equivalent commits on the prime branch, preserving merges (presumably by manually specifying the hashes of where the equivalent commits are on the rebased tree). How do I tell K′ that it needs to merge from H′ and J′? Or do I have to recreate these merge commits manually?

    If I do git rebase -p --onto B′ B L it fails to apply cleanly. I could rebase H onto B′ and M onto D′, and then recreate merge K myself, then rebase L onto K′ (and so on for other branches/merges not shown) but it would be a fair bit of work.

    I have looked at several other questions but none of them featured merges.

  • Git merge- Already up-to-date: hard reset?
  • Use git commit history to find project hot-spots?
  • Search the commit with the same file
  • Push changes on many files into separate branches
  • Git strategy to keep on applying my changes to someone else's updeting branch
  • Commit history on remote repository
  • 2 Solutions collect form web for “Rebasing merged trees in Git”

    Assuming this is either not a public repository, or any other users of the repository are ok with significant rewriting, the most efficient way to accomplish this is with git filter-branch. One of the possible filters is --parent-filter, which allows you to change the parentage of specific commits, somewhat similarly to grafting or rebasing a portion of the tree, but since you can also pass the --all option, you can accomplish the effect on multiple branches in one invocation. This could also be accomplished with a --commit-filter; but that’s a more general solution intended for changing other aspects of individual commits – not just the parents. You’d probably also want to use a --tag-name-filter cat to move any tags in the portions of the tree being rewritten.

    So the final command would look something like:

    git filter-branch --parent-filter <somescript> --tag-name-filter cat -- --all
    

    where <somescript> is either properly quoted/escaped bash code to replace A with A' for the B commit (details on exactly how the information is provided to the script and what the results of the script should be can be found in git help filter-branch), or the name of an actual shell script that accomplishes the same.

    There is also some cleanup to be done afterwards – filter-branch leaves your original branches in place, but with new names (refs/original/...) so you can recover if something doesn’t look right. There’s plenty of information out there on how to remove dead branches once you’re satisfied that filter-branch did what you wanted, and re-packing your repository to recover the storage space, so I won’t replicate that here…

    Have you tried using interactive rebasing? Basically, do git rebase -i A and git will fire up your text editor with the commits after A listed. You can then move commits around and squash commits into each other to your heart’s content.

    Git Baby is a git and github fan, let's start git clone.