Git submodules: what to do when you commit to (no branch)

Posted by Cliff Brake on 2010-06-17 | 3 Comments to Read

When using git submodules, eventually you’ll run into a situation where a workspace has checked out a submodule as (no branch), and you unknownly make modifications and commits to (no branch).  Now what?  It turns out Git has a very useful feature named reflog.  Reflog keeps a local time based log of all activity.  That means that as long as you do not garbage collect your workspace, you can go back to any point in time and get any commit that was made.  This is useful in a number of scenarios, but lets consider the case where we made two commits to a submodule in the (no branch) state.  We are then ready to push our changes to the upstream repo and we get:

cbrake@happy:/scratch/oe/oe-build-overo/openembedded.custom$ git push bec HEAD
error: unable to push to unqualified destination: HEAD
The destination refspec neither matches an existing ref on the remote nor
begins with refs/, and we are unable to guess a prefix based on the source ref.
error: failed to push some refs to 'git@git.bec-systems.com:openembedded.custom'

If we do a git log, we find we are on the infamous (no branch).

cbrake@happy:/scratch/oe/oe-build-overo/openembedded.custom$ git branch
* (no branch)
  master

At this point we may wonder what to do.  How do we get these changes onto the master branch?  Using git reflog, we can view all commits and changes to our local repository based on time.

cbrake@happy:/scratch/oe/oe-build-overo/openembedded.custom$ git reflog
6d195b3 HEAD@{0}: commit: add recipe for qt-embedded image
4cf1bd6 HEAD@{1}: commit: add touchscreen utilities
bcc673c HEAD@{2}: checkout: moving from master to bcc673c9824e916a7ec6c04f60a17116af539423
56d9def HEAD@{3}: commit: add more features
5286f87 HEAD@{4}: commit: rename debug image
90896de HEAD@{5}: pull : Fast-forward
5cc3f3b HEAD@{6}: checkout: moving from 90896deb2a25f0d40b1e6305a0ad994f932f22d8 to master
90896de HEAD@{7}: checkout: moving from master to 90896deb2a25f0d40b1e6305a0ad994f932f22d8

Git will keep our keeps commits to (no branch) even though we might switch to another name branch.  And using git reflog, we can easily find these commits and merge them to the master branch.

cbrake@happy:/scratch/oe/oe-build-overo/openembedded.custom$ git checkout master
Previous HEAD position was 6d195b3... add recipe for qt-embedded image
Switched to branch 'master'
Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
cbrake@happy:/scratch/oe/oe-build-overo/openembedded.custom$ git reflog
56d9def HEAD@{0}: checkout: moving from 6d195b3909553b04cba3d3ac182076a2c6b866b2 to master
6d195b3 HEAD@{1}: commit: add recipe for qt-embedded image
4cf1bd6 HEAD@{2}: commit: add touchscreen utilities
bcc673c HEAD@{3}: checkout: moving from master to bcc673c9824e916a7ec6c04f60a17116af539423
56d9def HEAD@{4}: commit: add more features
5286f87 HEAD@{5}: commit: rename debug image
90896de HEAD@{6}: pull : Fast-forward
5cc3f3b HEAD@{7}: checkout: moving from 90896deb2a25f0d40b1e6305a0ad994f932f22d8 to master
90896de HEAD@{8}: checkout: moving from master to 90896deb2a25f0d40b1e6305a0ad994f932f22d8
cbrake@happy:/scratch/oe/oe-build-overo/openembedded.custom$ git merge 6d195b3
Updating 56d9def..6d195b3
Fast-forward
 recipes/images/bec-debug-image.bb       |   38 +++++++++++++++++++-----------
 recipes/images/bec-qt-embedded-image.bb |    8 ++++++
 2 files changed, 32 insertions(+), 14 deletions(-)
 create mode 100644 recipes/images/bec-qt-embedded-image.bb

At this point, the changes have been merged to the master branch, and we can now push to our public repository:

cbrake@happy:/scratch/oe/oe-build-overo/openembedded.custom$ git push bec HEAD
Counting objects: 14, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (10/10), 1.13 KiB, done.
Total 10 (delta 3), reused 0 (delta 0)
To git@git.bec-systems.com:openembedded.custom
   bcc673c..6d195b3  HEAD -> master

Git reflog can also be used to restore commits that you decided at one point to throw away with “git reset –hard HEAD~2″, etc.  As long as you don’t garbage collect the repo, they are simply dangling state and always still exist.  This is just another example of the ways git can be very confusing, but also very powerful if you understand how it works.

This screencast covers the operations in this article.

  • Edvinas said,

    This post just saved me 12 hours of hard work! :)

  • Elliot said,

    You just saved me a week’s worth of commits! Felt like reflogging myself afterwards. Cheers to you, sir!

  • nurav said,

    Good post with exact explanation I was looking for!