Swift Package Manager supports Git Submodules

I am a Software Engineer working on open source and enterprise mobile SDKs for iOS and MacOS developers written in Swift. From 🇩🇪 and happily living in 🇺🇸
Search for a command to run...

I am a Software Engineer working on open source and enterprise mobile SDKs for iOS and MacOS developers written in Swift. From 🇩🇪 and happily living in 🇺🇸
No comments yet. Be the first to comment.
WWDC26 kicked off on June 8, 2026. The information in this article reflects the information published by Apple on that date. There are 14 new frameworks. Name Description AccessoryAccess Manage

WWDC25 kicked off on June 9, 2025. The information in this article reflects the information published by Apple on that date. New Frameworks NameDescription AlarmKitSchedule prominent alarms and countdowns to help people manage their time. AVR...

WWDC25 is almost here, and I couldn’t be more excited! Whether you're attending the official events, community meetups, or just soaking in the energy around Cupertino, there’s no better time to connect, share ideas, and celebrate everything we love a...

In this blog post, I’ll share an observation and advice regarding the caching behavior of network responses by Apple’s APIs. If you are unfamiliar with caching of network responses then I recommend Apple’s article Accessing cached data that introduce...
WWDC24 kicked off on June 10, 2024. The information in this article reflects the information published by Apple on that date. New Frameworks NameDescription AccessorySetupKitUse AccessorySetupKit to discover accessories with Bluetooth or Wi-Fi...

Swift Package Manager allows you to define Dependencies to other packages.
import PackageDescription
let package = Package(
name: "MyPackage",
dependencies: [
.package(url: "https://github.com/apple/example-package-playingcard.git", from: "3.0.4"),
],
targets: [
.target(
name: "MyPackage",
dependencies: ["PlayingCard"]
),
.testTarget(
name: "MyPackageTests",
dependencies: ["MyPackage"]
),
]
)
Since Swift 5.3 you are also able to bundle images, data files, and other resources needed at runtime.
What about git submodules ?
You might be interested in using git submodules to share common code or resources between projects. An example is that you are building an iOS and an Android app. Both apps have different repositories, and you even modularized your iOS app with Swift packages. But in both apps you want to execute common code in a JavaScript engine. Hence you think about placing the shared JavaScript code into a git submodule.
There are misleading entries in the Swift Forums but if you dig deep enough you will find a comment about SwiftPM will automatically download submodules when fetching a Swift package’s source during the build process.
I created a repository with a git submodule, and I can confirm that SPM will initialize/update a git submodule if present in a Swift Package.


This is ensured by GitRepository.swift implementation in Swift Package Manager.
public func checkout(tag: String) throws {
// FIXME: Audit behavior with off-branch tags in remote repositories, we
// may need to take a little more care here.
// use barrier for write operations
try self.lock.withLock {
try callGit("reset", "--hard", tag,
failureMessage: "Couldn’t check out tag ‘\(tag)’")
try self.updateSubmoduleAndCleanNotOnQueue()
}
}
public func checkout(revision: Revision) throws {
// FIXME: Audit behavior with off-branch tags in remote repositories, we
// may need to take a little more care here.
// use barrier for write operations
try self.lock.withLock {
try callGit("checkout", "-f", revision.identifier,
failureMessage: "Couldn’t check out revision ‘\(revision.identifier)’")
try self.updateSubmoduleAndCleanNotOnQueue()
}
}
/// Initializes and updates the submodules, if any, and cleans left over the files and directories using git-clean.
private func updateSubmoduleAndCleanNotOnQueue() throws {
try self.callGit("submodule", "update", "--init", "--recursive",
failureMessage: "Couldn’t update repository submodules")
try self.callGit("clean", "-ffdx",
failureMessage: "Couldn’t clean repository submodules")
}
Note: I had cases that Xcode did not show the folder with the submodule content but the content was available in the respective checkout result that is stored in the DerivedData folder (example: ~/Library/Developer/Xcode/DerivedData/AppUsingPackage-randomString/SourcePackages/checkouts/SwiftPackageWithGitSubmodule).