Skip to content

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

  1. Tightly Integrated Subprojects: When the subproject is essential and frequently changes alongside the main project.
  2. Simpler Contributor Workflow: Contributors don’t need to initialize submodules separately.
  3. History Integration: The full history of the subproject is stored in the main repository, making it easier to view changes.
  4. No Dependency on .gitmodules: You don’t rely on a separate .gitmodules file like in submodules.
  5. Avoiding Detached HEAD Issues: Subtrees don't require additional checkout mechanisms that submodules often need.
  6. 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
Adds the 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
- Merges updates from the subproject repository into the main repository.

Example:

git subtree pull --prefix=lib/awesome-tool https://github.com/example/awesome-tool.git main --squash
Fetches and integrates updates from the 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
- Pushes changes made in the subtree back to the subproject repository.

Example:

git subtree push --prefix=lib/awesome-tool https://github.com/example/awesome-tool.git main
Updates the 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.
  • 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

  1. Integrated Projects: For repositories where the subproject is an integral part of the main repository.
  2. Frequent Updates: When you frequently update the subproject and prefer a simpler workflow for contributors.
  3. 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.