Given:
Assume a simple repository with a single file, main.c
on the master
branch. At some point in the development history, branchA
is created from master
, and development continues in both master
and branchA
. However, after some time branchA
has evolved to be a separate project from the one in master
. (See below for background information.)
Problem: I want to bring these code bases back into a single branch, preserving the files in both code bases as well as their respective development histories. So, I want to merge branchA
back into the master
branch in a sub-directory called subdirA
. The result should be both a main.c
and a subdirA/main.c
in master
. The git log
output of specific files right after the merge should show the same commits as the git log
output of the files in each branch just before the merge.
Current Approach: Here's the solution I've come up with so far, based on approaches to merging one repository into another as a subfolder [1]:
- In
branchA
, git move all files to a new foldersubdirA
and commit - Switch to
master
and start a merge withbranchA
:git merge -s ours --no-commit branchA
- Read the branch commits into index:
git read-tree --prefix=/ -u branchA
- Commit:
git commit -m "Imported branchA into subdirA subfolder, with full history"
Issues:
Following the above, I have a repository with the desired structure and containing the full history of all commits. However, git log main.c
shows the commits modifying main.c
along both development paths. Similarly, git log --follow subdirA/main.c
shows the same full set of commits from both code bases. Since these files were not actually merged into one, it means there are commits shown in one file's history which did not actually modify that file - very confusing.
The only way I have found to separate the histories is to locate the first commit on the master
and branchA
branches after the branch point (assume we tag them as master_tag
and branchA_tag
, respectively) and using these to explicitly walk back along the appropriate path, for example: git log --ancestry-path master_tag.. main.c
and git log --follow --ancestry-path branchA_tag.. subdirA/main.c
.
Some problems with the above are:
- Must manually specify the ancestor (and which ancestor, based on file location), otherwise get unrelated commit history for files
- Most GUI tools don't allow (or not easily) such history viewing, and so show unrelated commits
- History output of the above doesn't go back to before the split
Question: So, does anyone know a way to merge the branches together to achieve the repository structure defined above, yet keep the history of the two code bases from co-mingling after the merge?
Background: I have a git repository (legacy, migrated from SVN) which I am trying to reorganize. The original SVN repo had two branches which are separate components of a larger project. Imagine that someone split a single application into separate client/server components by making a new branch for the server, and keeping client development in the trunk, and that would be pretty close to the current state. I would like to combine these two sets of code back into one branch, keeping the development history of both easily accessible after the fact. The idea being that most development is done on the two components together, so keeping them in the same branch makes development, release, etc. simpler.
References: [1] http://nuclearsquid.com/writings/subtree-merging-and-you/