Consider the following questions: How do you handle project dependencies with git? Our project is made up of multiple inter-dependent repositories. Currently we manage those with svn:externals. What’s the best way to handle those with git? How do you split a very big repository in smaller components using git? These are some examples of the most asked questions we got at the European leg of our recent Getting Git Right tour. The topic appears to be a big pain point for many software teams adopting git, so in this article I’ll try to shed some light on the issue. Obviously project dependencies and build infrastructure are two intertwined areas, and even internally at Atlassian a discussion sparked on the “Future of Builds”. Having separate repositories as opposed to having a single one can make some things harder. But it’s a relatively natural – sometimes mandatory – step in the evolution of a software project for at least two major reasons: increasing build times, and shared dependencies between projects. Painting with broad strokes: guidelines and sub-optimal solutions So back to the question: How do you track and manage project dependencies with git? If possible, you don’t! Jokes aside, let me answer with broad strokes first and dig deeper afterwards. Please realize that there is no silver bullet – in git or otherwise – that will painlessly solve all the issues related with project dependencies. Once a project grows over a certain size, it makes sense to split it in logical components, but don’t wait to have a 100 million plus lines of code in a single repository before you do. So the following are just guidelines so that you can devise your own approach. First choice: Use an appropriate build/dependency tool instead of git A dependency management tool is my current recommended way forward to handle the growing pains and the build times of sizeable projects. Keep your modules separated in individual repositories and manage their interdependency using a tool built for the job. There is one for (almost) every technology stack out there. Some examples: Maven (or Gradle) if you use Java Npm for node apps Grunt or Bower,etc if you use Javascript Pip and requirements.txt if you use Python RubyGems,Bundler if you use Ruby NuGet for .NET CMake for C++ CocoaPods for Cocoa iOS apps In Go the build/dependency infrastructure is somewhat built into the language (though people have been working on a more complete solution, see godep) For our Git server Stash we use both Maven and Bower. At build time the tool of choice will pull the right versions of the dependencies so that your master project can be built. Some of these tools have limitations and make assumptions that are not optimal, but are proven and viable. The pains of splitting your project Simplistically at the start of a project everything is packed in one build. But as the project grows, that may result in your build to be too slow – at which point you need “caching,” which is where dependency management comes in. This by the way means submodules (see below) lend themselves very well to dynamic languages for example. Basically I think most people need to worry […]