gitgit-commitgit-detached-head

How to commit files in detached head mode to a branch


I ended up in a weird situation where I checkout a previous commit on my branch v4.1.0-rc12. I've modified some files around and I want to commit it to the v4.1.0-rc12 branch.

Now that HEAD pointer is in detached mode since I checked out a previous commit, how do I commit this changes to v4.1.0-rc12 branch in detached mode?

I wish I had done "revert" instead of "checkout" the commit hash.

Is there any possible solution to commit the edited files and add it to my v4.1.0-rc12 branch?

This is what my "git reflog" shows

 441bfac HEAD@{0}: commit: Resolved #110
 dc00e4f HEAD@{1}: checkout: moving from v4.1.0-rc12 to dc00e4f
 2542748 HEAD@{2}: commit: Login & SignUp revamp (Broken)
 dc00e4f HEAD@{3}: commit: Resolved #109 and #110
 4472914 HEAD@{4}: commit: Resolved #108

I want to save 441bfac to v4.1.0-rc12

Any help or notion would be appreciated.


Solution

  • Method 1:

    $ git checkout v4.1.0-rc12 branch
    (see if it succeeds, if so):
    $ git add ...     # if / as needed
    $ git commit
    

    This might not work, because the git checkout step will refuse to switch to the branch, if (and only if) said switching will wipe out the changes you've already made.

    The git checkout step will succeed, and carry your changes along, if it can.

    If the git checkout step succeeds, this is by far the easiest way to deal with it all. If not, proceed to alternate methods.


    Method 2 (avi's answer):

    $ git checkout -b tempbranch
    $ git add ...      # as and if needed
    $ git commit
    

    This (the -b tempbranch) creates a new, temporary branch pointing to the commit at which you detached your HEAD earlier. The git commit then creates a new commit on this temporary branch:

              o--o--o   <-- v4.1.0-rc12 branch
             /
    ...--o--o
             \
              o         <-- tempbranch
    

    Now you can git checkout whatever you like, and the commit you made on tempbranch is permanently stored in your repository (well, permanent unless/until you delete the name tempbranch), which enables you to copy stuff from it whenever you want.


    Method 3:

    $ git stash
    $ git checkout v4.1.0-rc12 branch
    $ git stash apply    # or even "git stash pop" but I prefer "apply"
    ... check everything out ...
    ... if it all looks right ...
    $ git stash drop     # "git stash pop" means "apply and then auto-drop"
    

    What git stash does is make a commit (well, actually two commits) that are not on any branch. The effect is the same as when you make the temporary branch. That leaves the problem of deleting the non-branch when you're done with it, so git stash drop deletes the unnamed non-branch that holds the commits.

    The git stash apply step essentially (though it's more complicated than this) cherry-picks the commit that git stash made, wherever you are now: so this is like cherry-picking the commit you made on tempbranch.

    Note that git stash pop automatically invokes git stash drop, even if the result of the git stash apply is a mess, you've lost your temporary commits if you pop but not if you apply. If everything goes well there's no real difference and pop is more convenient; this is just a case of leaving a better bread-crumb trail in case things go bad.


    (My personal preference, incidentally, is for method 1 first if possible, then usually 2, then 3, but sometimes—when I am sure it's going to work—I'll prefer method 3 to method 2.)