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.

  • how to add files/folders to gitignore in intellij GUI?
  • Why GIT does not detect the difference between the file mode 644 and 664?
  • When cloning an svn repository into git, should I clone only trunk, or the entire repo?
  • The following untracked working tree files would be overwritten by
  • Checkout subfolder in git
  • Calling git from Java with command line
  • 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.

  • Does GitHub garbage collect dangling commits referenced in pull requests?
  • Local Git branch has diverged from origin following an interactive rebase
  • Stage untracked files for commit without staging tracked file changes
  • Remove multiple deleted items at once from Git - Command line
  • Git shows the error “does not appear to be a git repository fatal: The remote end hung up unexpectedly”
  • Semantic UI in .gitignore
  • 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.