Subtree
The git subtree
command is a Git tool for managing subprojects within a single repository. Unlike submodules, it embeds the subproject's history directly into the main repository, simplifying management. This is especially useful when you want tighter integration with the subproject without requiring external references like submodules.
When to Use git subtree
- Tightly Integrated Subprojects: When the subproject is essential and frequently changes alongside the main project.
- Simpler Contributor Workflow: Contributors don’t need to initialize submodules separately.
- History Integration: The full history of the subproject is stored in the main repository, making it easier to view changes.
- No Dependency on
.gitmodules
: You don’t rely on a separate.gitmodules
file like in submodules. - Avoiding Detached HEAD Issues: Subtrees don't require additional checkout mechanisms that submodules often need.
- Fewer Permissions Issues: Avoid the need for separate permissions or authentication for the subproject.
Key git subtree
Commands with Examples
Adding a Subtree
git subtree add --prefix=subdir-name https://github.com/username/repo.git main --squash
--prefix=subdir-name
: Directory where the subproject will be added.https://github.com/username/repo.git
: URL of the subproject repository.main
: The branch of the subproject to add.--squash
: Combines the subproject history into a single commit.
Example:
git subtree add --prefix=lib/awesome-tool https://github.com/example/awesome-tool.git main --squash
awesome-tool
repository under the lib/
directory of the main project.
Pulling Updates from the Subproject
git subtree pull --prefix=subdir-name https://github.com/username/repo.git branch-name --squash
Example:
git subtree pull --prefix=lib/awesome-tool https://github.com/example/awesome-tool.git main --squash
main
branch of the awesome-tool
subproject.
Pushing Changes Back to the Subproject
git subtree push --prefix=subdir-name https://github.com/username/repo.git branch-name
Example:
git subtree push --prefix=lib/awesome-tool https://github.com/example/awesome-tool.git main
main
branch of the awesome-tool
repository with changes made in the lib/awesome-tool
directory.
Splitting the Subproject
If you want to extract the subtree into its own repository:
git subtree split --prefix=subdir-name --branch=new-branch-name
--prefix=subdir-name
: Directory of the subtree.--branch=new-branch-name
: Name of the branch to hold the extracted history.
Example:
git subtree split --prefix=lib/awesome-tool --branch=split-awesome-tool
Creates a new branch (split-awesome-tool
) containing only the history of lib/awesome-tool
.
Alternatives to git subtree
git submodule
- Use Case: When you want to maintain a lightweight reference to a subproject.
- Pros:
- Keeps the main repository smaller.
- Submodule repositories can be independently managed.
- Cons:
- Requires additional steps for contributors (e.g.,
git submodule update --init
). - Detached HEAD issues are common.
- Requires additional steps for contributors (e.g.,
- Example:
git submodule add https://github.com/example/awesome-tool.git lib/awesome-tool
Manual Merging
- Use Case: For occasional or ad-hoc integration of external projects.
- Pros:
- No special tools or commands required.
- Cons:
- No history integration.
- Tedious for frequent updates.
- Example:
- Copy files manually and commit them with a message like "Update from upstream."
git merge
with a Remote
- Use Case: For integrating changes from a related project without splitting it into a subtree.
- Pros:
- Simple and straightforward.
- Cons:
- Does not separate the subproject clearly.
- Example:
git remote add upstream https://github.com/example/awesome-tool.git git fetch upstream git merge upstream/main
Comparison of Subtree vs. Submodule
Feature | Subtree | Submodule |
---|---|---|
History | Full history of subproject | No history of subproject |
Ease of Use | Easier for contributors | Requires additional setup |
Integration | Fully integrated | Lightweight reference |
Repository Size | Larger due to full history | Smaller |
Decoupling | Tightly coupled | Loosely coupled |
When to Use git subtree
- Integrated Projects: For repositories where the subproject is an integral part of the main repository.
- Frequent Updates: When you frequently update the subproject and prefer a simpler workflow for contributors.
- No External Dependency: If you want all history and changes in a single repository.
By using git subtree
, you achieve a balance between full integration and flexibility for managing subprojects. It is an excellent choice for projects where simplicity and full history integration are priorities.