Git submodule tutorial – Cocoapods might not be the solution.

Recently I’ve been in lots of discussions about git submodule Vs cocoapods, and I noticed that, unfortunately, lots of developers never tried submodules, like the normal flow nowadays is to just go directly to cocoapods. Lots of arguments on why cocoapods is better are actually something that git submodules also does very well, like “semantic versioning”. Truth be told, I don’t think cocoapods is all bad, but I do think it tries to solve problems that doesn’t exist and add new issues in the process.

Some reasons I don’t like cocoapods:
– It’s *very* intrusive.
– It adds a dependency to your project (The irony);
– It adds problems that you wouldn’t have using other solutions;
– You have to wait for cocoapods support when you try new things (Swift, Xcode Beta, etc);
– If you want a different config from the one cocoapods generates, you’re going to have a bad time.
– Way more cumbersome to maintain forks;
– Too much “behind the scenes” configs;
– Very slow compared to git submodules;

But to be fair, there are some positive notes:
– Easier to add an external lib to your project;
– If you don’t like to configure the project your way, it will just do it for you;
– Easier to see what dependencies are outdated;
– Easier to try a lib and discard it;

In my opinion the disadvantages of it succeeds the advantages by a large amount. I never thought “Man, adding a new lib/framework to my iOS project sure is tedious and time-consuming, I wish there was a way to improve it” simply because I think it’s very fast to do it manually and it doesn’t compromise the control you have over *your* project.

This is my justification on writing this post, I just want to show how simple and easy is to use git submodule, a well supported, simple, non intrusive and robust way to add third party libs to your project, without adding any new dependency (Assuming you’re using git).

How does it works?
It’s pretty simple actually, just imagine that the git submodule is nothing more than another git repo inside your own repo. This is particularly good when you work on both projects (main and submodule) because the workflow is basically the same, when you want to work on the submodule project, the way you add,commit,push files is everything you already know and love.

On this tutorial I’ll create a simple Xcode project and add AFNetworking to it. I’ll assume that you already have a git repository up and running with your Xcode project, so I’ll skip these steps and go right to the submodule part.

Cool, you have your project, and you want to add AFNetworking as a submodule, right? Easy, what I like to do is to create a folder on my project structure to host all my submodules, making it easier to find the dependencies. So, let’s create the folder: (Assuming you are in the root level of your project)
mkdir -p Frameworks/External

Now, the *hard* part, adding the submodule:
git submodule add Frameworks/External/AFNetworking

That’s it, the submodule is now added to your project, if you look at your root folder, you’ll see that now you have a new file called “.gitmodules”, if you open it you’ll see something like this:

[submodule "SubmoduleTutorial/Frameworks/External/AFNetworking"]
path = SubmoduleTutorial/Frameworks/External/AFNetworking
url =

This is the config of your submodule, simple, easy to understand what’s going on, no mystery.

Now, the  final step is to just add the files you want from AFNetworking to your project, how you want it, whatever way you think is best, no auto config, no hidden settings.

What I like to do is to just add a group called Frameworks and drag the folder there:


That’s it, basically the entire list of steps are:
– git submodule add (repo url) (local path);
– Add files you want to your project;
– Done;

You can see on my github link how the submodule is represented by a link:
( that goes directly to the host page. Pretty cool, right?

Of course, this is just scraping the surface of what can be done with submodules, but I just wanted to show how simple is to add a submodule to your project.

And later, if you want to clone your repo (or any repo that has a submodule) there’s just one extra step.
git submodule update --init --recursive
This is your “pod install”, but it’s incredible fast compared to the cocoapods alternative (The recursive flag is optional, as you might think, it’s just to get submodules of submodules if that’s the case, but it’s a rare scenario).

This is the link of the repository I used for this tutorial: (Submodule Tutorial)

As I said before, cocoapods is not all bad, but I really think developers should give it a try to git submodule because I’m pretty sure it will solve 90% of problems without adding yet another project dependency. Also, it’s way smarter to decide if it’s better to use cocoapods or submodules once you have at least the bare minimum experience with both approaches so you can weight the options and make the best decision. I’m not a cocoapods hater, as all technologies, cocoapods is just a tool that you need to consider to solve your problems, but I do believe lots of developers think that it’s the only option out there where it’s not true, there’s already a pretty solid solution ready to go with their git repo.
Here’s a link of the oficial documentation ( Documentation )

Also, while we are on the subject, I strongly recommend this read, an awesome post about having to think a bit before adding third-party libs to your apps.

2 thoughts on “Git submodule tutorial – Cocoapods might not be the solution.

  1. Good post, i agree.
    I don’t like cocoapods, i think it just overcomplicates things.
    It’s like Interface Builder vs programmatically created views.
    It looks good on the outside, it’s a giant pain to maintain (the IB).

  2. First of all, great post!

    I never used cocoapods myself, but I use a custom git extension developed by the LogMeIn (where I work) that has some of the features I believe cocoapods targets as well.

    Git submodule works in a way that each submodule is pinned to a specific commit rather than a branch. That creates a problem when you have submodules with submodules, that is, when your project depends on other projects which have other dependencies.

    In that scenario, if you run “git submodule update —init —recursive”, you will be all set, however your project’s submodules and their submodules will be on a detached head state. That means if you want to modify something on a leaf submodule, you will have to do a commit in every parent submodule in that hierarchy (all the way up to your project’s branch). This can be a real issue if you have multiple teams actively working on these dependencies.

    The extension we use provides submodules pinned to a branch, so you can setup your project’s branch to use a given submodule’s branch and so on. Once this is done, you can change any submodule/project in the hierarchy without having to do maintenance commits on the whole hierarchy.

    It also ensures the whole team will always be using the correct version/combination of submodules.

    So my opinion is that if your project doesn’t have a complex hierarchy of dependencies, you are probably better off with plain git submodules (as you said). But if that is not the case, considering cocoapods or some other framework might come in handy.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s