Table of Contents

Overview

The good and the bad of git subtree (mostly the good).

Synopsis

NAME
       git-subtree - Merge subtrees together and split repository into subtrees

SYNOPSIS
       git subtree add   -P <prefix> <commit>
       git subtree add   -P <prefix> <repository> <ref>
       git subtree pull  -P <prefix> <repository> <ref>
       git subtree push  -P <prefix> <repository> <ref>
       git subtree merge -P <prefix> <commit>
       git subtree split -P <prefix> [OPTIONS] [<commit>]
       
       ... snip ...
       
DESCRIPTION
       Subtrees allow subprojects to be included within a subdirectory of the main project,
       optionally including the subproject’s entire history.

       For example, you could include the source code for a library as a subdirectory of your
       application.

       Subtrees are not to be confused with submodules, which are meant for the same task. Unlike
       submodules, subtrees do not need any special constructions (like .gitmodule files or
       gitlinks) be present in your repository, and do not force end-users of your repository to
       do anything special or to understand how subtrees work. A subtree is just a subdirectory
       that can be committed to, branched, and merged along with your project in any way you want.
       
       ... snip...
       
OPTIONS
       -q, --quiet
           Suppress unnecessary output messages on stderr.

       -d, --debug
           Produce even more unnecessary output messages on stderr.

       -P <prefix>, --prefix=<prefix>
           Specify the path in the repository to the subtree you want to manipulate. This option
           is mandatory for all commands.

       -m <message>, --message=<message>
           This option is only valid for add, merge and pull (unsure). Specify <message> as the
           commit message for the merge commit.

The good and the bad

The good:

The bad:

Setting up a subtree

Start a new branch

$ git checkout -b subtree

Start a subtree, and examine it

The synopsis:

$ git subtree add -P <prefix> <repository> <ref>

The example:

$ git subtree add \
  --prefix .vim/bundle/tpope-vim-surround \
  https://bitbucket.org/vim-plugins-mirror/vim-surround.git \
  master \
  --squash
git fetch https://bitbucket.org/vim-plugins-mirror/vim-surround.git master
warning: no common commits
remote: Counting objects: 338, done.
remote: Compressing objects: 100% (133/133), done.
remote: Total 338 (delta 101), reused 338 (delta 101)
Receiving objects: 100% (338/338), 71.46 KiB | 46.00 KiB/s, done.
Resolving deltas: 100% (101/101), done.
From https://bitbucket.org/vim-plugins-mirror/vim-surround
 * branch            master     -> FETCH_HEAD
Added dir '.vim/bundle/tpope-vim-surround'
$
$ tree .vim
.vim
└── bundle
    └── tpope-vim-surround
        ├── doc
        │   └── surround.txt
        ├── plugin
        │   └── surround.vim
        └── README.markdown

4 directories, 3 files
$
$ git log --oneline
cc770c1 (HEAD -> subtree) Merge commit 'bd61f717bcc5d8569846d875952d6aefab987dd1' as '.vim/bundle/tpope-vim-surround'
bd61f71 Squashed '.vim/bundle/tpope-vim-surround/' content from commit 02199ea
... snip ...
$

To manually update subtree

Synopsis:

$ git subtree pull -P <prefix> <repository> <ref>

Example:

$ git subtree pull \
  --prefix .vim/bundle/tpope-vim-surround \
  https://bitbucket.org/vim-plugins-mirror/vim-surround.git \
  master \
  --squash
$

Add the subproject as a remote

Add a remote (-f means fetch immediately):

$ git remote add \
  -f \
  tpope-vim-surround \
  https://bitbucket.org/vim-plugins-mirror/vim-surround.git
$

Add the subtree:

$ git subtree add \
  --prefix .vim/bundle/tpope-vim-surround \
  tpope-vim-surround \
  master \
  --squash
$

To update at a later date:

$ git fetch tpope-vim-surround master
$ git subtree pull \
  --prefix .vim/bundle/tpope-vim-surround \
  tpope-vim-surround \
  master \
  --squash
$