Introduction
In software development, it often happens that projects evolve from independent repositories into a single unified project. When you need to merge two Git repositories while retaining their complete history, there are several strategies available, each suitable for different scenarios. This tutorial will guide you through merging one repository (Project A) into another (Project B), placing the former as a subdirectory within the latter.
Prerequisites
- Basic knowledge of Git commands and workflow.
- Both projects should be initialized with Git (
git init
). - Ensure that both repositories are on the same machine or accessible via network paths.
Method 1: Using git-filter-repo
The git-filter-repo
tool is an efficient way to rewrite history, making it ideal for moving project directories. It’s a modern alternative to the older git filter-branch
.
Steps
-
Navigate to Project A: Open your terminal and navigate to the directory of Project A.
cd path/to/project-a
-
Rewrite History: Use
git-filter-repo
to move all contents into a subdirectory named after Project A. This command rewrites history so that all files appear under this new directory.git filter-repo --to-subdirectory-filter project-a
-
Add and Merge into Project B:
-
Move to the Project B directory.
cd path/to/project-b
-
Add Project A as a remote to Project B.
git remote add project-a /path/to/project-a
-
Fetch and merge the history from Project A into Project B, allowing unrelated histories. This option is necessary for merging two separate repositories with no shared history.
git fetch project-a --tags git merge --allow-unrelated-histories project-a/main
-
Finally, clean up by removing the remote reference to Project A.
git remote remove project-a
-
-
Verification: Verify that all files from Project A are now under a subdirectory in Project B. Use
git log
orgit status
to check if everything merged correctly.
Method 2: Using Subtree Merge
The subtree merge strategy is useful when you want the history of both projects visible as part of a unified history tree.
Steps
-
Add Remote for Project A:
-
Navigate to Project B and add Project A as a remote.
cd path/to/project-b git remote add project-a /path/to/project-a
-
-
Fetch from Project A: Fetch all data from Project A including tags.
git fetch project-a --tags
-
Merge with Subtree:
-
Use the subtree merge strategy to bring in Project A under a specified subdirectory (
projectA
).git read-tree --prefix=projectA/ -u project-a/main git commit -m "Merged project A as a subdirectory"
-
-
Pull Changes: Complete the integration by pulling changes with subtree merge.
git pull project-a main --allow-unrelated-histories
Method 3: Using git-subtree
git-subtree
provides an easy way to manage a repository as a subdirectory within another. This method is useful for projects that need occasional synchronization but maintain separate development histories.
Steps
-
Add Project A: Use
git subtree add
from the root of Project B, specifying the path where Project A should reside.git subtree add --prefix=projectA git://github.com/user/project-a main
-
Subsequent Updates:
-
For future updates, use:
git subtree pull --prefix=projectA git://github.com/user/project-a main
-
Best Practices and Tips
- Backup First: Always make backups of your repositories before performing history rewrites.
- Test Thoroughly: After merging, thoroughly test the integrated project to ensure everything works as expected.
- Clean Up Branches: Remove any unnecessary branches or remote references after completing the merge.
By following these methods, you can effectively combine two Git projects while preserving their individual histories. Choose the approach that best fits your project’s structure and workflow needs.