Tutorial: Managing iPhone Third Party Library Dependencies Using Git+Braid

By
On May 21, 2009
Guest author Doug Barth is the Lead Architect at Interactive Mediums the mobile-marketing technology company behind the SMS marketing tool TextMe.

Git is a distributed version control system (DVCS) that has been gaining adoption in both the Ruby and iPhone development communities. DVCS’s allow a developer to work with version control without connecting to a remote, central repository. All commits, branches, tags, and query operations occur locally. Because these operations are local, they are fast. To share your work, DVCS’s provide operations to push to or pull changes from a remote repository.

I am currently finishing up a contract iPhone project that makes use of several open source libraries. Since the final project is being delivered to the client in source code form, I needed an easy checkout and build experience for the client. I opted to include copies of the third party projects in a Vendor directory in my project’s source tree.

I like to keep the third party code in a separate group (Vendor) in my XCode project. In that directory I further break up each project into its own group. Some libraries are consumed by building the source files with your project. For those projects, I simply add the files using the Add -> Existing Files… menu option. Other libraries are setup to create a static library, which is built using a dependent XCode project. For those I follow the build instructions to add the dependent project and its library, making sure to use paths relative to the project root.

Git includes a feature called submodules which could be used to manage this code. However, submodules are not cloned when the root project is cloned. Instead, the user must init and update the submodules after the initial clone of the root repsoitory. Updating a submodule is also tricky. The user making the change has to carefully make changes in both the submodule and parent project, making sure to push changes in the submodule before pushing changes in the parent project. Consuming those changes is not much easier. That user needs to run git submodule update after pulling new changes.

Enter braid

Braid is Ruby gem that provides a command line tool to manage vendored project directories in a Git repository. Braid supports pulling from upstream projects hosted using git or subversion. By using braid, it is easy to check in a vendor branch of an upstream project using the braid add command. When the project changes upstream, you can easily pull those changes using braid update. You can even make changes to the vendored code and see those changes using braid diff.

Braid manages copies of the code in the host project. This means that other developers do not need to interact with braid to get the latest vendored code, it is included in the changes they get when using git alone. You only need braid if you want to get updates from the upstream project or see what local changes have been committed.

Installing braid

Installing braid is quite simple since Ruby and Rubygems are included with OS X. Simply run the following command in Terminal.

$ sudo gem install braid

Once that command finishes, you will now have new commmand “braid” in your path. Braid includes simple help messages which can be printed using “braid help”

$ braid help
NAME
  braid

SYNOPSIS
  braid (add|update|remove|setup|diff|version) [options]+

DESCRIPTION
braid is a simple tool to help track git or svn repositories inside a git
repository.

Run 'braid help commandname' for more details.

All operations will be executed in the braid/track branch.
You can then merge back or cherry-pick changes.

PARAMETERS
  --help, -h

Adding a new library

Adding a library to your project is simple using the braid add command. Your working directory needs to be clean in order to add or update a braid managed directory. As an example, let’s add the Three20 project at Vendor/three20.

$ braid add git://github.com/joehewitt/three20.git Vendor/three20
Braid: Adding git mirror of 'git://github.com/joehewitt/three20.git'.
Braid: Setup: Creating remote for 'Vendor/three20'.
Braid: Added mirror 'Vendor/three20' at '3274e6d'

If we check the commit that braid created, we will see that braid committed all the source for the project. It also created a .braids file, which it uses to keep track of all the braid managed directories.

$ cat .braids
---
Vendor/three20:
squashed: true
url: git://github.com/joehewitt/three20.git
type: git
revision: 3274e6d0515bbbcbdbabe8ef2a411ae1efded092
branch: master
remote: braid/Vendor/three20

The squashed value controls whether braid adds a single commit or all the history from the vendored project. The default is true since most users do not want the vendored project history included in their project’s history.

Updating an existing library

Once a project is installed with braid, future upstream changes can easily be merged in using the braid update command. The update command grabs the latest changes from the upstream project and commits them to your project as a single commit.

Running braid update will update all braid managed directories to their latest versions. Running braid update subdirectory will only update a single directory to the latest versions.

If you have committed any changes in a braid managed directory, braid will attempt to the merge the upstream changes with your version of the code. If there is a conflict, you will need to resolve the conflict and commit the pending version.

Drawbacks of using braid

Braid works really well for pulling down changes from upstream. But what if you want to submit a patch upstream? Braid includes a command, braid diff, which will show the differences between your version of the project and the upstream version. Unfortunately, there is no way to push local commits to the upstream project, nor format patches from each local commit. If you find you need to push changes back often, a git submodule may be a better fit.

We asked Doug to write this article for us after he left a comment about Git+Braid in our earlier tutorial on using static libraries to share code across projects. See something in this or another article you want to say something about? Leave a comment!

0 responses to “Tutorial: Managing iPhone Third Party Library Dependencies Using Git+Braid”

  1. Doug Barth says:

    git subtrees are definitely another valid option. Braid is using all the same plumbing. Braid adds support svn backed upstream projects as well.

    Unfortunately, neither adds support for easily pushing changes back. This effort seems promising though: https://alumnit.ca/~apenwarr/log/?m=200904#30

  2. pTracker says:

    Excellent post, Doug. This will come in very handy for another project I’m involved in where we will face the same issues of reusability and client access to source code as you did. Thanks for sharing.

  3. Cristi Balan says:

    Doug, thanks for the very nice writeup :).

    You’ll be thrilled to find out that the other author of braid, Norbert, already has push working in his development branch. We need to add a few tests to it and it will be good to go. If you’re feeling adventurous, his branch is here:

    https://github.com/norbert/braid

    However, we’ve been a bit busy with client work and, not really needing this yet, it got a bit delayed.

    Also, before another important release, we’d like to work on braid switch too, to allow people to easily change the tracked branch after a mirror is added.

    ps: Nice pic 🙂