Reputation: 91
For historical reasons I currently have the following project structure:
part0:
part1:
The binaries of the project are built by checking out commits of the same date from the two repositories, so I need e.g. part0 - master(01.04.2013) and part1 - master(01.04.2013). Checking out the parts from different dates won't work.
I now want to combine these two repositories into one, with the structure
where the commits in master are ordered by commit date from part0 - master and part1 - master.
If I use the described merge schemes I found, I will get a history of
part0 - master (everything) + part1 - master (everything) afterwards
So a checkout of any commit will not work, because either I only get part0 (before having merged part1) or I get the newest part0 - master with an outdated part1 - master.
Upvotes: 3
Views: 137
Reputation: 91
I finally puzzled the solution out of the links I posted above. First the problem in pictures:
repo0: A -- B -- C -- D -- E \ F -- G -- H repo1: A' -- B' -- C' -- D' -- E' \ F' -- G' -- H'
Where the commits A and A' correspond and to get the project in a running form, you need to checkout A and A' simultaneously into their respective directories, say proj0 and proj1.
In the repositories the files and directories are put in /.
The target repository should look like this:
A -- A' -- B -- B' -- C -- C' -- D -- D' -- E -- E' \ F -- F' -- G -- G' -- H -- H'
So I first did a move of all the contents of the repositories commits into the final directories with this (of course in a copy):
git clone --mirror path/repo0 repo0 git filter-branch --tree-filter "(mkdir -p proj0 ; find * -maxdepth 0 ! -iname proj0 -exec mv {} proj0/ \;)" -- --all git clone --mirror path/repo1 repo1 git filter-branch --tree-filter "(mkdir -p proj1 ; find * -maxdepth 0 ! -iname proj1 -exec mv {} proj1/ \;)" -- --all
Now I could merge the two, first I create a new repository with the old ones as remotes:
git init new git remote add proj0 path/repo0 git remote add proj1 path/repo1 git fetch --all
Then I merge branch by branch, I just name them BranchE and BranchH. As they exist from the beginning of the project, I had to get the very first commit, this is done with the dummy-branch:
git checkout -b dummy remotes/proj0/BranchE git checkout -b start `git log --topo-order --reverse | head -n 1 | sed s/"commit \(.*\)"/"\1"/` git checkout -b merge start git merge -m "merge" remotes/proj1/BranchE git rebase --onto start start merge git branch -D start git branch -D dummy git branch -m merge BranchE
I did the same for BranchH. The drawback until now is, that the histroy looks now like this:
A -- A' -- B -- B' -- C -- C' -- D -- D' -- E -- E' \ \ \ A' -- B -- B' -- F -- F' -- G -- G' -- H -- H'
The last thing to do is to bring together the similar parts of the history, this is done with this command:
git checkout BranchE git rebase `git log --oneline | grep "commit comment of last common commit B'" | sed -r s/"(^[a-f0-9]+) .*"/"\1"/` BranchH
Et voilá, you get the desired result.
Upvotes: 2