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.