Working with Git Subtrees And Trellis

When working with Trellis/ Bedrock/ Sage for wordpress development how do we keep each repo up to date within the wider context of a project?

I like to use Trellis/ Bedrock/ Sage for wordpress development, but found that the respective repositories for the three constituent parts of this 'stack' are in pretty lively development and change frequently. I wanted to find a solution that could easily keep each repository up to date within my development project. Enter the forest of subtrees...

This method isn't peculiar to the roots stack, it can be applied to any project with nested dependencies.

I'm going to assume that this is a shiny new project, so first I create a private bitbucket repo. This is because I don't want any sensitive config data or passwords in a public repository and because our team uses bitbucket.

mkdir sites/shiny-new-project

Within that project folder I usually setup something like this:

shiny-new-project
 |- DB
 |- PROJECT
 |- site
 |- trellis
 .gitignore

The 'DB' folder allows for database backups and the 'PROJECT' folder allows for designs and miscellaneous project files to be stored within my project folder. These two files and all their contents are gitignored.

First let's set up our 'project repo':

$ git init

And add it to bitbucket

$ git remote add origin git@bitbucket.org:{username}/shiny-new-project.git
$ touch .gitignore
$ git add .
$ git commit -m "initial commit"

Apparently it is necessary to already have a commit in the project repo - so creating the gitignore file takes care of that for us.

Next I'm going to define a remote for trellis in the project and check it out into it's own branch.

$ git remote add trellis https://github.com/roots/trellis.git
$ git fetch trellis
$ git checkout -b trellis trellis/master

Now the project has a copy of the trellis/master in the trelis branch. You may want to add the remote of your own fork - this example just uses the roots repos.

We want trellis to live within our project inside it's own directory. For that I can use the git read-tree command.

So I switch to the master branch of the project and run the command

$ git checkout master
$ git read-tree --prefix=trellis/ -u trellis/master

Now all the trellis files are in the trellis folder. Any changes I make within the trellis folder for project specific server configs can be commited and pushed to the private master project repo.

Finalize with a commit:

$ git commit -m "add trellis subtree"

Bedrock

Now lets add bedrock to our project in the same way:

$ git remote add bedrock https://github.com/roots/bedrock.git
$ git fetch bedrock
$ git checkout -b bedrock bedrock/master
$ git checkout master

now get bedrock inside the site directory:

$ git read-tree --prefix=site/ -u bedrock/master

Finalize with a commit:

$ git commit -m "add bedrock subtree"

Sage

Now for the sage starter theme:

$ git remote add sage https://github.com/roots/sage.git
$ git fetch sage
$ git checkout -b sage sage/master
$ git checkout master

Get sage inside the sites theme directory:

$ git read-tree --prefix=site/web/app/themes/sage -u sage/master

Finalize with a commit:

$ git commit -m "add sage subtree"

So now we have all the dependent repos for our project in their folders inside our main project repo - kind of like if we had just downloaded each of them - but much more easily updated...

Updating

To update one of the subtrees all I need to do is checkout the corresponding branch and pull/ merge. To avoid merging the histories I can use the --squash command

$ git checkout trellis
$ git pull
$ git checkout master
$ git merge --squash -s subtree --no-commit trellis
$ git commit -m "Update trellis from trellis/master"

UPDATING EDIT

It came to light on the roots forums that the updating method above is a bit buggy because trees were over-writing each other. So the merge command needs to be more specific.

$ git checkout trellis
$ git pull
$ git checkout master
$ git merge -X subtree=trellis/ --squash trellis/master
$ git commit -m "Update trellis from trellis/master"

That's it!

Any changes I make within the trellis, site(bedrock) or sage theme folder can be commited and pushed to the project master (or any other) branch within my 'Master' bitbucket repo - so Trellis deploy tasks work as expected.


Code and Process