Skip to main content

Managing External Dependencies with Git Subtrees

Pascal Spörri
Author
Pascal Spörri
Simplify external code management with Git subtrees.

Git subtrees are a powerful feature that let you integrate another Git repository into your own as a subdirectory. Unlike Git submodules, which maintain a reference to an external repo, subtrees physically embed the other repository’s contents within your own history-making them easier to manage in many cases.

This post explains how to use Git subtrees to add and update external repositories within your project.


What Is a Git Subtree?
#

A Git subtree imports the entire history of an external project into a subdirectory of your repository, usually as a squashed commit (one combined commit, rather than the full log).

This differs from Git submodules, which store only a pointer to a specific commit in another repository. Subtrees are better when:

  • You want to vendor dependencies directly into your repo
  • You want to avoid extra tooling for submodules
  • You want everything under one roof (e.g., for deployment or archiving)

Commands
#

Adding a Git Repository as a Subtree
#

You can add another repository as a subtree like this:

git subtree add --prefix=target_dir git_remote.git branch --squash
  • --prefix=target_dir: Specifies the directory within your repo to place the external project.
  • git_remote.git: URL or path to the external Git repository.
  • branch: The branch to import.
  • --squash: Combines the subtree’s history into a single commit.

This results in a commit that looks like this:

commit f5ddddda7d42d06cd7883f7c495124f7dd4f503f
Merge: ed74e04 688ea1d
Author: Pascal <pascal@localhost>
Date:   Fri Sep 16 12:02:58 2016 +0200

Merge commit '688ea1de2af40776bfda21e59a14f97e6204e294' as 'foo'

commit 688ea1de2af40776bfda21e59a14f97e6204e294
Author: Pascal <pascal@localhost>
Date:   Fri Sep 16 12:02:58 2016 +0200

    Squashed 'target_dir/' content from commit 62372d7

    git-subtree-dir: target_dir
    git-subtree-split: 62372d78da03021a81c12972e483d3d074469be7

Updating a Git Subtree
#

To pull in changes from the upstream project:

git subtree pull --prefix=target_dir git_remote.git branch --squash

This adds a new squashed commit with the updated content.


Further Reading
#

For an in-depth comparison of subtrees vs submodules, see Atlassian’s write-up: 👉 The Power of Git Subtree.