Git submodules are the way to include the repository as the subdirectory of another repository. It can be useful for including the external projects within the main project while keeping their versioning independent. JGit is the pure java library for the Git functionalities and it can allowing to manage the repositories including the submodules programmatically.
Prerequisites
- Basic understanding of the Java and Git concepts.
- JDK and IntelliJ idea installed in your local system.
- Maven for building dependency management.
Main Concept: Working with submodules in JGit
What are Submodules?
Submodules are the repositories nested inside the parent repository. It can allow you to the incorporate and manage the dependencies on the other repositories and making it easy to share the code across the multiple projects.
Why Use Submodules?
They are useful when the project depends on the other projects and we want to maintain the independence of the each repository history and updates. For the example, if you have the project that relies on the specific library hosted in the separate repository and we can add it as the submodule.
Implementation of the Working with submodules in JGit
Step 1: Create the Maven Project
Create the maven project using IntelliJ Idea. Once create the project then the file structure looks like the below image.

Step 2: Add the JGit Dependency
Open the pom.xml and add the below JGit dependency into the project.
<!-- https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit -->
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>6.9.0.202403050737-r</version>
</dependency>
Step 3: Create the JGitSubModuleExample Class
package com.auxentios;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import java.io.File;
import java.io.IOException;
public class JGitSubmoduleExample {
public static void main(String[] args) {
String repoPath = "C:/Users/Mahesh/Desktop/modules3";
String submoduleUri = "https://github.com/iammahesh123/E-Commerce-Backend-Spring-Microservices";
String submodulePath = "submodule";
try {
// Initialize a repository with a submodule
initRepositoryWithSubmodule(repoPath, submoduleUri, submodulePath);
// Clone a repository with submodules
cloneRepositoryWithSubmodules("https://github.com/iammahesh123/Task-Management-System-using-microservices", "C:/Users/Mahesh/Desktop/modules2");
// Update submodules
updateSubmodules("C:/Users/Mahesh/Desktop/clonedRepo");
// Commit changes in submodules
commitSubmoduleChanges("C:/Users/Mahesh/Desktop/clonedRepo", submodulePath);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void initRepositoryWithSubmodule(String repoPath, String submoduleUri, String submodulePath) throws GitAPIException {
Git git = Git.init().setDirectory(new File(repoPath)).call();
git.submoduleAdd().setURI(submoduleUri).setPath(submodulePath).call();
System.out.println("Repository initialized with submodule");
}
private static void cloneRepositoryWithSubmodules(String repoUri, String clonePath) throws GitAPIException {
Git git = Git.cloneRepository().setURI(repoUri).setDirectory(new File(clonePath)).call();
git.submoduleInit().call();
git.submoduleUpdate().call();
System.out.println("Repository cloned with submodules");
}
private static void updateSubmodules(String repoPath) throws IOException, GitAPIException {
Git git = Git.open(new File(repoPath));
git.submoduleUpdate().call();
System.out.println("Submodules updated");
}
private static void commitSubmoduleChanges(String repoPath, String submodulePath) throws IOException, GitAPIException {
Git git = Git.open(new File(repoPath));
Git submoduleGit = Git.open(new File(repoPath + "/" + submodulePath));
submoduleGit.add().addFilepattern(".").call();
submoduleGit.commit().setMessage("Submodule changes").call();
submoduleGit.push().call();
git.add().addFilepattern(submodulePath).call();
git.commit().setMessage("Updated submodule reference").call();
git.push().call();
System.out.println("Changes committed and pushed");
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.auxentios</groupId>
<artifactId>jgit-submodules</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit -->
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>6.9.0.202403050737-r</version>
</dependency>
</dependencies>
</project>
Step 4: Run the application
It will show the below output.

Conclusion
Working with the submodules in the git enables to manage the dependencies on the external repositories within the main project seamlessly. By the initializing repositories, adding the submodules and fetching the updates programmatically. We can maintain the modularity and independencies of the codebases while leveraging the capabilities of the JGit. This approach can ensure the efficient and organized management of the complex project with the multiple dependencies.