User Tools

Site Tools


git_subtree

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:

  • Management of a simple workflow is easy.
  • Older version of Git are supported (even older than v1.5.2).
  • The sub-project’s code is available right after the clone of the super project is done.
  • git subtree does not require users of your repository to learn anything new. They can ignore the fact that you are using git subtree to manage dependencies.
  • git subtree does not add new metadata files like git submodule does (i.e., .gitmodule).
  • Contents of the module can be modified without having a separate repository copy of the dependency somewhere else.

The bad:

  • You must learn about a new merge strategy (i.e. git subtree).
  • Contributing code back upstream for the sub-projects is slightly more complicated.
  • The responsibility of not mixing super and sub-project code in commits lies with you

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
$
git_subtree.txt · Last modified: 2018/02/13 17:05 by rpjday