views:

42

answers:

2

I have two projects, A and B. They were poorly divided, because A had to run one part before B and another part after B. So I decided to merge them. B's contents were copied into A's working directory, committed, and work continued from there.

Of course, B's history was not preserved in the copy-paste. I want to fix this before it's forgotten and bites someone later.

How can I modify A's repository's history to show an import from B's repository?

I think I need to introduce a new root node, copy B's stuff onto that root, then replace the 'add new files' commit with 'merge rooted B into A'. I have no idea how to do any of those.

+2  A: 

It sounds like you want to do a subtree merge.

mipadi
This interleaves commits to B and A if merge B into A, whereas I want them to be separate until the merge. If I run it from a new repository they stay separate, but merge at the latest commit. I don't know how to target the correct node in the history.
Strilanc
+2  A: 

You have to first do a subtree merge onto the commit before the copy-paste, then rebase the following commits onto the result of the merge. Make sure you remember the --preserve-merges switch for rebase, or the two trees will end up interleaved instead of merged.

Commands:

'(First, write down the ids of the current head and the commit before the copy paste)'
'(Second, do this on a copy of the repository in case you make a mistake)'

#Set the head to the commit before the copy paste (and checkout that commit)
git reset idOfCommitBeforeCopyPaste --hard

#Merge-in the master branch from the other repository, using magic
git remote add -f otherName other/repository/path
git merge -s ours --no-commit otherName/master
git read-tree --prefix=otherName/ -u otherName/master
git commit -m "Subtree merge from other"

'(Now you many want to move some files and do a commit)'
'(Write down the id of the current head, which is the result of the merge)'

#Apply all following commits to become equivalent to the up-to-date commit, and checkout
git reset headIdFromBeforeWeStarted --hard
git rebase mergeCommitId --preserve-merges

'(You may have conflicts; resolve them in the normal way then rebase --continue)'
'(To verify you did not change the present, compare the resulting working directory)'
Strilanc