Fork me on GitHub!

git-subbranch

git-subbranch Build Status

This may be of interest for you if you host project pages in a GitHub Pages branch (or in a similar setup) and need to derive the contents of the branch from the project itself (e.g., artifacts, documentation, ...).

The problem

The gh-pages branch in GitHub is special -- its contents are interpreted as a Jekyll or HTML website and provided on http://username.github.io/projectname. The source files, on the other hand, are supposed to be located in another branch, e.g., master, with possible further feature/hotfix/... branches. If the contents of the gh-pages branch depend on the contents of the "main" branches, there are several obvious options for organizing this:

  1. Switching between branches: One checkout, current branch is chosen via git checkout.
  2. Side by side: Two checkouts, but with different checked-out branches. (@chrisjacob discusses a setup using a "grand-parent" directory.)
  3. Contents of the gh-pages branch are contained redundantly in a subdirectory. (Uses git subtree, described here, here, here, here, and my favorite approach until now).
  4. Create Git tree and commit objects manually via plumbing.

None of them are really satisfactory. Perhaps this can be done better.

Proposition

Demonstration

make[1]: Entering directory '/home/muelleki/git/git-subbranch'
rm -rf /tmp/git-subbranch
cp -r . /tmp/git-subbranch
cd /tmp/git-subbranch && make test
make[2]: Entering directory '/tmp/git-subbranch'
./test.sh
Initialized empty Git repository in /tmp/git-subbranch/test/.git/
[master (root-commit) e5f345d] initial
[master 8b93dab] initial README.md
 1 file changed, 1 insertion(+)
 create mode 100644 README.md
[master 0ca2f89] ignore gh-pages-dir
 1 file changed, 1 insertion(+)
 create mode 100644 .gitignore
[gh-pages (root-commit) fd849aa] initial (pages)
Deleted branch master (was 0ca2f89).
Branch gh-pages set up to track remote branch gh-pages from origin.
  gh-pages fd849aa initial (pages)
* master   0ca2f89 ignore gh-pages-dir
* fd849aa initial (pages)
* 0ca2f89 ignore gh-pages-dir
* 8b93dab initial README.md
* e5f345d initial
Merge made by the 'ours' strategy.
[gh-pages 1847666] deploy
 1 file changed, 1 insertion(+)
 create mode 100644 README.dm
Branch gh-pages set up to track remote branch gh-pages from origin.
  gh-pages 1847666 deploy
* master   0ca2f89 ignore gh-pages-dir
* 1847666 deploy
*   8299d3f Merge remote-tracking branch 'origin/master' into gh-pages
|\  
| * 0ca2f89 ignore gh-pages-dir
| * 8b93dab initial README.md
| * e5f345d initial
* fd849aa initial (pages)
[master a54a5eb] More stuff
 1 file changed, 1 insertion(+)
[master 4489387] Even more stuff
 1 file changed, 1 insertion(+)
Merge made by the 'ours' strategy.
[gh-pages b5de71f] deploy
 1 file changed, 2 insertions(+)
[master 3661a0c] Oops, forgot
 1 file changed, 1 insertion(+)
Merge made by the 'ours' strategy.
[gh-pages eb11832] deploy
 1 file changed, 1 insertion(+)
Branch gh-pages set up to track remote branch gh-pages from origin.
  gh-pages eb11832 deploy
* master   3661a0c Oops, forgot
* eb11832 deploy
*   24c6555 Merge remote-tracking branch 'origin/master' into gh-pages
|\  
| * 3661a0c Oops, forgot
* | b5de71f deploy
* |   407e9e0 Merge remote-tracking branch 'origin/master' into gh-pages
|\ \  
| |/  
| * 4489387 Even more stuff
| * a54a5eb More stuff
* | 1847666 deploy
* |   8299d3f Merge remote-tracking branch 'origin/master' into gh-pages
|\ \  
| |/  
| * 0ca2f89 ignore gh-pages-dir
| * 8b93dab initial README.md
| * e5f345d initial
* fd849aa initial (pages)
gh-pages-dir
README.md
README.dm
initial README.md
More stuff
Even more stuff
Oops, forgot
Oops, forgot
Even more stuff
More stuff
initial README.md
make[2]: Leaving directory '/tmp/git-subbranch'
make[1]: Leaving directory '/home/muelleki/git/git-subbranch'

Documentation

The file functions defines a few verbs, the interesting ones have a with git_subbranch_ prefix:

In day-to-day use, the usual sequence of commands will be link -> commit -> push, although they can be interchanged arbitrarily. In particular, if you never link, the two branches remain completely separate.

Comparison

To switching between branches

To parallel structures

To redundant storage

To Git plumbing commands

Summary

The setup described here seems to work for me, although this site (and the commands presented here) is in a very early stage. I hope others find this useful too, and this sketch evolves into a more mature tool.