Dependency Management Using Git Submodules
In this Dependency Management tutorial you’ll learn how to use Git Submodules to manage both internal and external dependencies for your project. By Andy Obusek.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Dependency Management Using Git Submodules
30 mins
- Getting Started
- What Is Dependency Management?
- Dependency Management Tools
- Working With A Private Dependency
- Connecting a Private Dependency
- Pulling Changes From A Private Dependency
- Working With A 3rd Party Dependency
- Adding Alamofire
- Removing A Dependency
- Wiring It All Up
- The Imagga API
- Where to Go From Here?
- Bonus: Cloning A Repository With Submodules
Pulling Changes From A Private Dependency
When sharing code between projects, you’ll often find you need to make changes to the shared code, and also make those changes available to other projects. Git Submodules make this easy.
You’ll add some code to ImaggaRouter, commit those changes, then use those changes from PhotoTagger.
Add a new Swift file to the ImaggaRouter project and name it ImaggaRouter.swift. Replace its contents with:
import Foundation
public enum ImaggaRouter {
static let baseURLPath = "http://api.imagga.com/v1"
static let authenticationToken = "Basic xxx"
case content
case tags(String)
case colors(String)
var path: String {
switch self {
case .content:
return "/content"
case .tags:
return "/tagging"
case .colors:
return "/colors"
}
}
}
This code begins to flesh out a routing enum
for interacting with the Imagga API.
Now add and commit these changes to the ImaggaRouter repository. From the root of the ImaggaRouter project, execute git commit -am "Add initial ImaggaRouter path"
:
ImaggaRouter|master⚡ ⇒ git commit -am "Add initial ImaggaRouter path"
[master 1523f10] Add initial ImaggaRouter path
3 files changed, 33 insertions(+)
rewrite ImaggaRouter.xcodeproj/project.xcworkspace/xcuserdata/andyo.xcuserdatad/UserInterfaceState.xcuserstate (80%)
create mode 100644 ImaggaRouter/ImaggaRouter.swift
ImaggaRouter|master ⇒
This adds the most recent changes (adding an initial implementation of ImaggaRouter.swift) to the local Git repository.
git commit
instead of using git add X; git commit -m "Message"
. The -am
will add all untracked files and any files with changes to the commit. So in this case you had multiple files with changes instead of doing multiple git add X
you managed to perform the functionality in one line.Now the private dependency has been updated with changes, it’s time to pull those into PhotoTagger.
From the root of the PhotoTagger project, navigate into the submodule folder for ImaggaRouter, and execute git pull
:
ImaggaRouter|master ⇒ pwd
/Users/andyo/Documents/AndyRW/PhotoTagger/Frameworks/Internal/ImaggaRouter
ImaggaRouter|master ⇒ git pull
Updating 1523f10..4d9e71a
Fast-forward
.gitignore | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ImaggaRouter.xcodeproj/project.xcworkspace/xcuserdata/andyo.xcuserdatad/UserInterfaceState.xcuserstate | Bin 9652 -> 9771 bytes
2 files changed, 66 insertions(+)
ImaggaRouter|master ⇒
This retrieves the latest changes from the submodule. You can verify this by opening ImaggaRouter.swift and taking a peek through for the changes you just made.
The submodule is maintained as a a separate Git repository within the main project’s folder hierarchy. This is useful to know because all the same Git commands can be used to inspect that repository as well.
For example, from the submodule folder Frameworks/Internal/ImaggaRouter, execute git log
to look at the commits for the submodule. Since you just updated it, the latest commit should be as you would expect:
commit 1523f10dda29649d5ee281e7f1a6dedff5a8779f
Author: Andy Obusek <andyo@xyz.com>
Date: Mon Feb 13 20:08:29 2017 -0500
Add initial ImaggaRouter path
... cut ...
And just to observe the differences, that this really is a separate repository, navigate back to the root folder of PhotoTagger and execute git log
:
ImaggaRouter|master ⇒ cd ../../..
PhotoTagger|master⚡ ⇒ pwd
/Users/andyo/Documents/AndyRW/PhotoTagger
PhotoTagger|master⚡ ⇒ git log
commit 7303c65cc0f18174cb4846f6abe5cbfb57e17607
Author: Andy Obusek <andyo@aweber.com>
Date: Mon Feb 13 20:24:13 2017 -0500
Add ImaggaRouter project to Xcode
Notice how the latest commit message is different? That’s one indication you’re in a different Git repository.
While you’re in the root folder of PhotoTagger, execute git status
:
PhotoTagger|master⚡ ⇒ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: Frameworks/Internal/ImaggaRouter (new commits)
Submodules changed but not updated:
* Frameworks/Internal/ImaggaRouter 1523f10...4d9e71a (1):
> Add initial ImaggaRouter path
no changes added to commit (use "git add" and/or "git commit -a")
PhotoTagger|master⚡ ⇒
This status message tells you three important pieces of information:
- There are local changes that haven’t been committed.
- There have been updates to the ImaggaRouter submodule.
- There are specific commits that are new in the ImaggaRouter submodule.
To finally integrate the latest changes to ImaggaRouter, execute git add .
followed by git commit -m "Update ImaggaRouter"
:
PhotoTagger|master⚡ ⇒ git add .
PhotoTagger|master⚡ ⇒ git commit -m "Update ImaggaRouter
dquote> "
[master ad3b7f8] Update ImaggaRouter
1 file changed, 1 insertion(+), 1 deletion(-)
PhotoTagger|master ⇒
You’ve now made changes to the private dependency and pulled those changes back into the main project. You’re getting pretty good at this! :]
Working With A 3rd Party Dependency
Now you’ll add Alamofire as a dependency to your project as a Git Submodule. Alamofire is a popular networking library for iOS.
Adding Alamofire
Adding an external dependency is very similar to a private dependency. The only difference from what you’ve done so far is you’ll add Alamofire via its public github.com repository.
From the root folder of PhotoTagger, create a new folder under Frameworks named “External” by executing the following:
mkdir Frameworks/External
Then execute git submodule add https://github.com/Alamofire/Alamofire.git Frameworks/External/Alamofire
:
PhotoTagger|master ⇒ mkdir Frameworks/External
PhotoTagger|master ⇒ git submodule add https://github.com/Alamofire/Alamofire.git Frameworks/External/Alamofire
Cloning into '/Users/andyo/Documents/AndyRW/PhotoTagger/Frameworks/External/Alamofire'...
remote: Counting objects: 5924, done.
remote: Total 5924 (delta 0), reused 0 (delta 0), pack-reused 5924
Receiving objects: 100% (5924/5924), 2.51 MiB | 4.86 MiB/s, done.
Resolving deltas: 100% (3937/3937), done.
PhotoTagger|master⚡ ⇒
This adds Alamofire as a Git Submodule into a new sub-folder named Frameworks/External/Alamofire.
Execute git status
to reveal the local repository’s knowledge of Alamofire needs to be committed.
To do this, execute git add .
followed by git commit -m 'Add Alamofire'
:
PhotoTagger|master⚡ ⇒ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: .gitmodules
new file: Frameworks/External/Alamofire
Submodule changes to be committed:
* Frameworks/External/Alamofire 0000000...fa3c6d0 (660):
> [PR #1927] Fixed bug in README example code around default headers.
PhotoTagger|master⚡ ⇒ git add .
PhotoTagger|master⚡ ⇒ git commit -m "Add Alamofire"
[master 1b3e30b] Add Alamofire
2 files changed, 4 insertions(+)
create mode 160000 Frameworks/External/Alamofire
PhotoTagger|master ⇒
Now you can add Alamofire.xcodeproj to your project.
Just as before with ImaggaRouter.xcodeproj, drag Alamofire.xcodeproj into your project.
To use Alamofire, you need to add the framework as a Linked Framework to the main PhotoTagger target’s General settings.
Adding an external dependency was as simple as that!
Sometimes you come across the need to remove a dependency. Maybe it’s an old library you’re ready to stop using. Or maybe you just wanted to try out that latest and greatest new hot framework. Either way, it’s good to know how to remove dependencies that have been added as Git Submodules.