I have one git repository which is included within another git repository; how can I merge the inner one into the outer one permanently while keeping its commit history? For a more illustrative explanation, here's my directory structure:
[dev]
> [ext]
...
> [libs]
...
> [tools]
...
The dev
is the root directory of my git repository A, which excludes everything from the ext
directory through a .gitignore rule. The ext
, in turn, is the root directory of my git repository B. I would like to only keep the repository A going forward, and for it to include everything under dev
, including the contents of ext
, while merging the commit history of B into A -- so that I have just the one repository containing all of the contents and also all of the history of A and B both.
There are no submodules involved; the separation of the repositories is done just through the exclusion rule on the outer repository.
What's the best way to do this?
Start by moving the contents of repository B (in ext
) to a new ext
directory inside the repository (i.e. <project>/ext/ext
).
$ cd ./ext
$ mkdir ext
$ for f in *; do git mv "$f" "./ext/$f"; done
This way the history of repository B will "remember" that it's source tree belongs in the ext
directory during the next step.
Don't forget to commit this change.
After that, you can enter repository A (the root project), add repository B as a remote, fetch its unrelated history, and then create a merge commit that inherits from both revision histories. Do note that you will need to pass --allow-unrelated-histories
to git-merge
to allow the merging of unrelated history. The description of this flag reads:
By default,
git merge
command refuses to merge histories that do not share a common ancestor. This option can be used to override this safety when merging histories of two projects that started their lives independently.
All told, these are the commands to be run:
# Add "repo B" as a remote of "repo A"
$ git remote add ext_repo ./ext
# Fetch the unrelated history of "repo B"
$ git fetch ext_repo
# Create a commit with parents from both repos histories.
$ git merge --allow-unrelated-histories ext_repo/main