Thursday, October 11, 2018

Working with Git Submodules

No comments

A submodule is a repository embedded inside another repository. The submodule has its own history; the repository it is embedded in is called a superproject. Submodules can be used for at least two different use cases:

1.     Using another project while maintaining independent history. Submodules allow you to contain the working tree of another project within your own working tree while keeping the history of both projects separate. 
2.     Splitting a (logically single) project into multiple repositories and tying them back together. 

Adding a repository as a submodule
Use the below command to add a new submodule .
$ git submodule add -b master [URL to Git repo] [TARGET DIR]

You should notice the new .gitmodules file in your directory. This is a configuration file that stores the mapping between the project’s URL and the local subdirectory you’ve pulled it into.You should see an entry like this :

[submodule "<submodule name>"]
               path = <submodule path>
               url = <repo URL>

If you have multiple submodules, you’ll have multiple entries in this file. It’s important to note that this file is version-controlled with your other files, like your .gitignore file. It’s pushed and pulled with the rest of your project. This is how other people who clone this project know where to get the submodule projects from.

Run the below command to see the changes in the working tree now . You will see that a new submodule is created and is yet to be committed.
git diff --cached --submodule

Now commit and push the changes .

$ git commit -am 'added new submodule'
$ git push origin master

Let’s see what our parent repository thinks about all this . In the main project’s base folder execute :
$ git submodule status
+3557a0e0f7280fb3aba18fb9035d204c7de6344f lib/ToProgress (0.1.1)

With "git submodule status", we're told which revision each Submodule is checked out at. The little "+" symbol in front of the hash is especially important: it tells us that the Submodule is at a different revision than is officially recorded in the parent repository. When performing a simple "git status" in the parent repository, we see that Git regards moving the Submodule's pointer as a change like any other:


$ git status
On branch master
Changes not staged for commit:
    (use "git add ..." to update what will be committed)
    (use "git checkout -- ..." to discard changes in working directory)
    modified:   lib/ToProgress (new commits)

We need to commit this to the repository in order to make it official:
$ $ git commit -a -m "Moved Submodule pointer to version 1.1.0"


 Refer the documentation for more details on working with git submodules.

Cloning a Project with Submodules

When you clone a project with a submodule in it , to get the files within the submodules you have to run two more commands in addition to  git clone . First run git clone using the below command :

$ git clone https://github.com/MainProject

Now run the below commands:

$ git submodule init
$ git submodule update

The init command initializes your local configuration file .The update command will fetch all the data from that project and check out the appropriate commit listed in your superproject.
You can also run the below command instead of running multiple command :

$ git clone --recurse-submodules https://github.com/MainProject

Now we are ready to add and modify files in the submodules .Always make sure to commit and push your changes from the submodule level followed by a commit and push at the main directory level so that the commit ids are reflected correctly at both the levels. For more information on working with submodules refer the documentation .








No comments :

Post a Comment