Git

Git Add Submodule Example

In this post, we feature a comprehensive Example on Git Add Submodule.

1. Introduction

An important concept in software development is reusability. When working on a software project you may have situations where a function or method is used in many places of an application. Rather than interspersing the function/method code throughout the application, it is useful to place it in a utility class. In a large project where you have many such classes, you may want to move them to a separate project.

If your codebase becomes very large, you may also want to consider creating subprojects. There are advantages to breaking up a large project into smaller projects. For example:

  • Smaller projects allow for easier code maintenance.
  • Child projects can be used in other parent projects, encouraging reuse.
  • The developer or developers can focus on a specific area of the business solution.

 
Let’s assume that these separate projects have their own Git repositories. How can you use the utility project within the main project? In Git, you can include the utility project by adding it as a submodule to the main project.

A submodule is a repository that is contained inside a subdirectory of another repository. Logically, it can be thought of child project of a parent project. Git tracking for the submodule is managed separately from that of the main project. Code that is developed by a 3rd party is often included as a submodule in Git. Themes and plugins in WordPress too are typically included as submodules when Git is used as the Version Control System.

In Git you can add, clone, update and remove submodules within the main project. In this example, we will demonstrate how to add a repository as a submodule of another repository.

1.1 Tools Used in this Example

  • Git 2.17

Git downloads are available here: https://git-scm.com/downloads.

2. Git Add Submodule Example

In this example, we will create a local repository that contains a utility class. We will then add the new repository as a submodule of an existing main project.

2.1 Download and Extract the Sample Project

First, download the “Submodule Demo” archive from the Download section and extract it in a directory of your choice.

$ ls -R
.:
demo/  ioutils/

./demo:
mvnw*  mvnw.cmd  pom.xml  src/

./demo/src:
main/  test/

./demo/src/main:
java/  resources/

./demo/src/main/java:
com/

./demo/src/main/java/com:
javacodegeeks/

./demo/src/main/java/com/javacodegeeks:
example/

./demo/src/main/java/com/javacodegeeks/example:
demo/

./demo/src/main/java/com/javacodegeeks/example/demo:
DemoApplication.java

./demo/src/main/resources:
application.properties

./demo/src/test:
java/

./demo/src/test/java:
com/

./demo/src/test/java/com:
javacodegeeks/

./demo/src/test/java/com/javacodegeeks:
example/

./demo/src/test/java/com/javacodegeeks/example:
demo/

./demo/src/test/java/com/javacodegeeks/example/demo:
DemoApplicationTests.java

./ioutils:
FileUtil.java

We have a main project (named “demo”) that is tracked in a local repository. If you view the Git config file, you will see configuration information for the main project.

$ cat .git/config
[core]
        repositoryformatversion = 0
        filemode = false
        bare = false
        logallrefupdates = true
        symlinks = false
        ignorecase = true

Let us suppose that the “demo” project uses file input/output operations. Let us further assume that these operations are used in many places within the application. With these points in mind, we created a utility class for those operations and placed it into its own project named “ioutils”. We’ll add the “ioutils” project to its own local Git repository next.

2.2 Create a Local Repository

Open a terminal (shell) in the “ioutils” directory where the archive was extracted and run the following command:

$ git init

Git init Command Output

Initialized empty Git repository in /Users/gilbertlopez/ioutils/.git/

This creates an empty Git repository. The repository metadata has been generated in the “.git” folder.

(Note: This folder is hidden by default as you would, typically, not edit its contents.)

2.3 Add and Commit the File to the Project Repository

Let’s add the file to the repository. Run the following command:

$ git add FileUtil.java

This will add the FileUtil.java file to the repository index. The file is now in the staging area.

Commit the file from the staging area to the repository with the following command:

$ git commit -m 'Initial commit of project'

Note: The -m option allows us to add a commit message inline.

Git commit Command Output

[master (root-commit) 45e1f63] initial commit
 1 file changed, 49 insertions(+)
 create mode 100644 FileUtil.java

2.4 Add a Submodule to the Main Project

Now that we have our utility class in its own Git repository, let’s add it as a submodule to the “demo” project. Run the following command:

git submodule add -f ../ioutils src/main/java/com/javacodegeeks/example/ioutils

Note: The -f option is used to force the creation of src/main/java/com/javacodegeeks/example/ioutils, the directory where we want the submodule to reside.

  • The first parameter (../ioutils) to the submodule add command specifies the location of the repository to be added as a submodule. This could be a local repository (“ioutils” in this example) or a remote repository, e.g. https://github.com/gilbertlopez/example.git. It probably goes without saying that you need to be able to clone the repository in order to add it as a submodule.
  • The second parameter (src/main/java/com/javacodegeeks/example/ioutils) specifies the subdirectory path of the main project where you want the ioutils repository to be integrated. If you omit this parameter, Git will add the subproject to directory named the same as the repository (in this case, “ioutils”).

Git Submodule Add Command Output

Cloning into 'C:/Users/Gilbert/gittest/demo/src/main/java/com/javacodegeeks/example/ioutils'...
done.
warning: LF will be replaced by CRLF in .gitmodules.
The file will have its original line endings in your working directory.

The add submodule command registered the ioutils repository within the main project repository’s configuration. It also cloned the repository into the /src/main/java/com/javacodegeeks/example/ioutils directory.

If you view the Git config file for the main project after running the submodule add command, you will notice an additional section.

$ cat .git/config
[core]
        repositoryformatversion = 0
        filemode = false
        bare = false
        logallrefupdates = true
        symlinks = false
        ignorecase = true
[submodule "src/main/java/com/javacodegeeks/example/ioutils"]
        url = C:/Users/Gilbert/gittest/ioutils
        active = true

This submodule is identified by the path where the ioutils repository resides. The ‘url’ value in the submodule section shows the repository URL link (or directory path for a local repository) of the submodule that Git uses to clone the project.

Next, check the status of the main project with the following command:

$ git status

Git status Command Output

On branch master
Changes to be committed:
  (use "git reset HEAD ..." to unstage)

        new file:   .gitmodules
        new file:   src/main/java/com/javacodegeeks/example/ioutils

The submodule add command staged two new files: “.gitmodules” and “src/main/java/com/javacodegeeks/example/ioutils”. (Submodule directories and their contents appear as a single file when viewed by the main project’s Git repository.) If you look in the ioutils subdirectory of the main project, you will see that FileUtil.java from the “ioutils” repository was cloned into that location.

It is important to note that main and submodule repositories track independently of each other. Go to the submodule’s directory (“src/main/java/com/javacodegeeks/example/ioutils”) and run the Git status command:

$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

As you can see, the submodule’s Git is unaware of any changes made to the main project.

The Git status for the main project provides some basic information about the staged files. You can get additional information by making the status command submodule-aware. Navigate back to the ‘demo’ directory and run the following command:

$ git config --global status.submoduleSummary true

Now run the Git status command again.

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD ..." to unstage)

	new file:   .gitmodules
	new file:   src/main/java/com/javacodegeeks/example/ioutils

Submodule changes to be committed:

* src/main/java/com/javacodegeeks/example/ioutils 0000000...a3255ca (1):
  > Initial commit

The status now shows that the remote repository has 1 commit and that the commit was an addition with the commit message ‘Initial commit’.

To commit the files from the staging area to the repository, run the following command:

$ git commit -m 'Added ioutils submodule'

Git commit Command Output

[master 992ad34] Added ioutils submodule
 2 files changed, 4 insertions(+)
 create mode 100644 .gitmodules
 create mode 160000 src/main/java/com/javacodegeeks/example/ioutils

2.5 View the .gitmodules File

Let’s take a look at the .gitmodules file.

$ cat .gitmodules
[submodule "src/main/java/com/javacodegeeks/example/ioutils"]
        path = src/main/java/com/javacodegeeks/example/ioutils
        url = ../ioutils

The .gitmodules file holds all the submodule configuration information for this project. The data contained in this file is read by Git when anyone clones our project. It is used to locate the submodule repository (url = ../ioutils) and to specify the subdirectory of the main project where the submodule will be integrated (path = src/main/java/com/javacodegeeks/example/ioutils).

2.6 View the Status of Submodules

If you simply want to see the locations of your submodules, use the following command:

$ git submodule status

Git submodule status Command Output

 e51bafee08eff11e55817d789d40fe96a216c4a7 src/main/java/com/javacodegeeks/example/ioutils (heads/master)

The output displays the SHA-1 of the currently checked out commit for each submodule in the main project and the path locations where the submodules reside. (In our example, there is only one submodule.)

3. Summary

Adding submodules is a great way of integrating other Git repositories to your main project, whether these repositories are from a 3rd party or projects you created yourself for reuse.

4. Download the Source Code

That was Git Add Submodule Example.

Download
You can download the full source code of this example here: Submodule Demo

Gilbert Lopez

Gilbert Lopez is an application developer and systems integration developer with experience building business solutions for large and medium-sized companies. He has worked on many Java EE projects. His roles have included lead developer, systems analyst, business analyst and consultant. Gilbert graduated from California State University in Los Angeles with a Bachelor of Science degree in Business.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button