0

I just started using git, I perfomed following activities:

  • Cloned a master repository in my pc
  • Created a new branch
  • added some folders in my pc folder

When I type git add *, git commit -m "test" or git status I receive:

Your branch is up-to-date with 'origin/release/1.1'.
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)
  (commit or discard the untracked or modified content in submodules)

        modified:   folder1 (modified content, untracked content)

no changes added to commit (use "git add" and/or "git commit -a")

If I type "git diff folder1" I receive

diff --git a/folder1 b/folder1
--- a/folder1
+++ b/folder1
@@ -1 +1 @@
-Subproject commit 87a8914c3775b5baa4653818d63458fe9c73cb5b
+Subproject commit 87a8914c3775b5baa4653818d63458fe9c73cb5b-dirty
torek
  • 448,244
  • 59
  • 642
  • 775
Jaime Ron
  • 11
  • 1

1 Answers1

0

This indicates that you need to make a commit in the submodule first.

What's going on here

A submodule is mostly just a second, separate Git repository. Let's also mention a terminology note here: the superproject is the non-submodule Git repository. This means where we say "in the superproject, X and Y are true" we mean that X and Y are the case in the repository that is not the submodule repository.

Meanwhile, the word "mostly" is here because there are several special conditions about this second, submodule, Git repository:

  • The URL for the submodule is recorded in a file named .gitmodules in the superproject.

  • The commit hash for the submodule is recorded in each commit in the superproject (one commit hash per superproject commit—well, more precisely, one per commit that actually uses that submodule). This is saved as if it were a file or directory whose name is the path name within the superproject to the subproject.

    Hence, if your submodule has path folder1 within the superproject, each specific commit in the superproject effectively tells Git: "This commit is expected to work provided the user goes into the other (submodule) repository and checks out this specific commit hash as a detached HEAD."

Note that it is impossible for the superproject to record anything but this one commit hash. That hash must identify the exact state of the submodule. If the submodule Git repository really is on that commit, and everything works, then this "expected to work" guarantee from the second bullet point above holds. But if the submodule Git repository is full of uncommitted modifications that are required to make the superproject work, this "expected to work" guarantee falls apart: the superproject says "use commit feedc0d..." but feedc0d..." is not the correct subproject contents.

When you run git status, Git notices that you are in a superproject that has a submodule. It runs another Git, on the other repository that represents the submodule, to get its git status. That other Git reports that there are modifications in the submodule.

When you run git diff, Git notices that you are in this superproject and runs another git diff on the submodule, just as git status did. That diff says that there are changes that probably need to be committed first.

Until you actually make the subproject commit, though, you can't tell your (superproject) Git to record the new commit has for the submodule. That new commit hash doesn't even exist yet—it won't exist, and cannot be known or computed, until you run git commit there, write up a commit message, and let your name and email address and the time of the commit all get written into the log. At that point, the subproject will have a new commit (on its detached HEAD), and you can now record that new commit's hash ID in the superproject.

Before you commit in the submodule ...

Because the submodule normally is in "detached HEAD" mode, any new commit you make naively will not be on a branch. This makes it more difficult to push the new commit to a branch in some upstream repository.

Remember, the submodule is a Git repository in its own right: to work in it, you must work in a Git repository, the way you normally would. That usually means that you should be on a branch—but because this repository is in use as a submodule, the superproject Git has taken you off the branch. Hence, before you commit there, you probably should get back on a branch. But which branch? This is where sub-modules earn their nickname, sob-modules. There may be a good branch to use here, but there may not be any good branch to use here.

For much more about dealing with this, see Git commit to common submodule (master branch). Since the bad old days, submodule support has improved significantly: you can now record a branch name in the superproject, and get the superproject's Git to tell the submodule's Git which branch to use. However, the detached HEAD stuff is still the default, and still gets in the way.

There is no one correct way to deal with all of this. There are a bunch of ways that do work, with varying advantages and disadvantages, and some ways that don't work at all. Don't use one of the ones that don't work. :-) Do make the submodule commit on some branch, even if you have to create a branch.

Then, step back into the superproject and git add the subproject's new commit hash. Be very careful not to accidentally add all the subproject's files, which is very easy to do by mistake via pathname completion. That is:

git add folder1

is correct, but:

git add folder1/

is not correct.1

Now that the superproject has the new (correct) hash ID ready to commit, you can make a new superproject commit using that. Note that you must push the submodule upstream before you push the superproject upstream since anyone who obtains the new superproject commit will need to be able to obtain the new commit from the submodule as well.


1Why, yes, I have done this. More than once, in fact.

Community
  • 1
  • 1
torek
  • 448,244
  • 59
  • 642
  • 775