Git Lost (and Git Submodules)

We've been using Git for a little while now in a Windows environment and we have been quite pleased with it and the capabilities it affords us as part with its decentralized workflow. We have a number of shared projects or "common libraries" that we use between projects. Because of this, we are using Git's submodules feature.

One small issue that we hit was when we would make changes to the code to the project in a submodule (for example, some scripting code in a submodule), we would want to commit and push those changes. Whenever we would attempt to commit, we would get one of two messages:

$ git push origin master

Everything up-to-date

That's frustrating. Things definitely were not up-to-date. We could do a "git log" and see the difference between the local repository and the remote repository. Why was it saying things were "up-to-date"?

Other times, we'd get an even more frustrating error message:

$ git push origin master

To git@……..

! [rejected] …. –> master (non-fast forward)

error failed to push …..

What kind of error message is that? The part that made it confusing was that "non-fast forward" means that I'm not working at the head—basically I'm working off an older comment and trying to push that to the head. That made no sense because a "git pull" wouldn't give me anything new.

The Ah-Ha Moment

Run "git status" while in the submodule. It will say "Not currently on any branch." There's the problem. If I'm not working on a branch (even master), Git has trouble. To remedy this, run "git checkout master" before you do any work in the submodule.

Of course, this is all by-design:

When you do "git submodule update" and pull all the submodules down, it doesn't check them out on a particular branch. According to the above article:

One major difference between "submodule update" and "submodule add" is that "update" checks out a specific commit, rather than the tip of a branch. It's like checking out a tag: the head is detached, so you're not working on a branch.

So that's the solution—checkout a branch first (even if it's master), do your work and push.