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.
This post just saved me 12 hours of hard work! 🙂
You just saved me a week’s worth of commits! Felt like reflogging myself afterwards. Cheers to you, sir!
Good post with exact explanation I was looking for!
Comments are closed.