In a large organization, you may have dozens or even hundreds of Git repositories. These repositories may have common configuration and scripts, or you may be working in a C++ project where you need to compile several repositories from source code. How do you achieve this without copy-pasting files everywhere?
In this guide, you will learn about git subtrees
as a solution to this problem. You will set up a repository and perform some common operations.
A basic understanding of the git command line and GitHub is assumed knowledge for this guide. You can watch GitHub Getting Started if you need a refresher.
Note: GitHub is in the process of changing its default branch name from master
to main
. This guide will use the term master
branch since it is the current default branch name at the time of writing. You can learn more about this change by reading GitHub's official documentation on renaming the default branch.
Over a period of several years, you may find yourself working across dozens of different computers.
You can keep the settings consistent across your various machines by creating a Git repository with your settings files saved inside.
These settings are usually saved in files prefixed with a dot, e.g., .vimrc
, .bashrc
, etc.
Therefore, this setting repository is named dotfiles
by convention.
As your dotfiles
project progresses, you may want to use scripts and configuration that other people have created.
You can leverage and contribute back to the open-source community by referencing these repositories inside your dotfiles
using git subtrees
.
One common use case is embedding VIM plugins that are published as GitHub repositories into your dotfiles
repository.
To start using git subtrees
in this way, first create a dotfiles
repository.
1cd ~
2mkdir dotfiles
3cd dotfiles
4git init
5touch readme.md
6git add . && git commit -m "initial commit"
Note that these are bash commands. If you are on Windows, you can execute them in git bash
.
You have created a dotfiles
repository with a blank readme file.
Within your dotfiles
project, create a folder vim/pack/github/
to store your plugins.
This folder structure is important so that VIM will automatically detect and run the plugin.
You will place the contents of other git repositories inside this folder.
To do this, run the git subtree add
command.
1git subtree add --prefix vim/pack/github/vim-sensible [email protected]:tpope/vim-sensible.git master --squash
This command will embed the master branch of Tim Pope's VIM-sensible in your dotfiles.
Also note that you used the --squash
flag to compress the history.
You can run this command several times to embed multiple repositories.
With one or more subtrees, you may want to update to a specific branch or git tag.
You can do this by running the git subtree pull
command.
1git subtree pull --prefix vim/pack/github/vim-sensible/ [email protected]:tpope/vim-sensible.git master --squash
This creates a new commit and squashes any changes on top your dotfiles
repository.
As a good open-source citizen, when you find and fix bugs you will want to share your fixes with the community.
git subtree
makes this easy since you don't need to separately check out that nested repository.
To do this, you will perform the following steps:
1. Fork the nested repository, such as vim-sensible
, on GitHub.
2. Commit changes in your dotfiles
repository.
3. Run the below command to push to your fork.
1git subtree push --prefix vim/pack/github/vim-sensible/ [email protected]:chinwobble/vim-sensible.git issue-xxx
dotfiles
.Note that when pushing, you changed the remote to your own fork and you are pushing to a new branch, in the example above, it's issue-xxxx
.
If you are working on a GitHub issue, you may want to use the issue number as the branch name.
git subtree
is a good option to nest one repository in another. It does not require users to learn extra commands to access the nested repositories.
You can learn more about this feature by reading About Git subtree merges.