How to save changes when in detached-head state?
Asked Answered
B

4

20

Working with Git, I had to go back to a specific commit. I made some changes and I now want to commit them. What is a proper way of doing this?

My project is now in detached-HEAD state. Will my changes be saved if I make a commit with

git commit

? Otherwise, what should I do to not lose my changes?

Braden answered 22/6, 2015 at 15:8 Comment(6)
I made some changes and now want to save them. Please be more specific: what do you mean by "save"? You mainly have two options: commit, or stash. Either one will "save" your changes in some sense. Which are you referring to? Also, you may want to create a branch.Fivefinger
I want to commit my changes.Braden
I've edited your question accordingly.Fivefinger
What do you want to happen to the older commits that are ahead of you? I.e, you went "back" to a commit so there's some commits "in front" of that commit. Do you still care about those? (and have they been pushed upstream to other people, and do you care about those people)Moreover
I want to merge "in front" commits with this which in detached head state. There are some errors "in front" that's why I back to previous commit.Braden
I think you want to re-apply existing "in front" commits over a changed parent commit . Does that sound right? Sounds like you want git rebase <commit to edit> -i, then follow guide to interactive rebaseMoreover
M
45

Disclaimer: git isn't complicated, it's just versatile. Don't be scared off just because I've rambled into a long answer :)

You had:
master: a-b-c-d-e-f

and wanted to change c. You did:
* git checkout c (avoid checking out commits in future. Move the branch head instead)
* changed some files

You are in:

master: a-b-c-d-e-f
             \uncommitted-work,detached

If you want to re-apply d-e-f on top of your changed "c"

(If you have pushed, people downstream will be have to recover from upstream rebase)

  1. git stash .
  2. git checkout master
  3. git stash pop (resolve conflicts)
  4. git stage .
  5. git commit -m "temporary name for g"
  6. (master: a-b-c-d-e-f-g)
  7. git rebase c -i ("re-apply my current branch on to point c, and let me manipulate the commits interactively", i.e, re-parent (rebase) d-e-f onto a new c)
  8. Follow guide to interactive rebase. You want to re-order g so it's after c, then change the rebase command from pick to fixup. dd to delete a line, P to place it, i to enter insert mode to type "fixup" then :wq to save and exit vim.
  9. (master: a-b-c'-d'-e'-f', where c' is the result of you merging g and c during the rebase. d-e-f have become d'-e'-f' as their ancestry has changed so they're not the "same" commits as far as git is concerned, but their contents remain the same)

If you want to undo d-e-f (and rewrite history as if you never made them)

(If you have pushed, people downstream will be have to recover from upstream rebase) :

  1. git stash .
  2. git checkout master
  3. (master: a-b-c-d-e-f, with stashed files originally based upon c)
  4. git reset --hard c (discard all files and commits on master since c)
  5. (master: a-b-c, with stashed files)
  6. git stash pop (resolve conflicts)
  7. (master: a-b-c-*)
  8. git stage .
  9. git commit -m "description of g"
  10. (master: a-b-c-g)

If you want to undo d-e-f (but keep them in history)

  1. git stash
  2. git revert --no-commit d
  3. git revert --no-commit e
  4. git revert --no-commit f
  5. git push
  6. git stash pop (will be no conflicts)
  7. git stage .
  8. git commit -m "Undo d-e-f in order to fix..."
  9. git push

If you have git push d-e-f, and you want to keep them separate:

Sounds like your new changes are for a new branch off master. git branch <foo>.

Moreover answered 22/6, 2015 at 15:47 Comment(2)
Amazing comprehensive answer providing insight into multiple techniques and workflows. You deserve way more credit / attention than this has gotten. just ONE upvote? Jesus.Matazzoni
Great answer! Thanks!! Helped me a lot!Fortunio
B
8

Create a new branch from this commit and THEN do the commit:

git checkout -b <branchname>
git commit 

Assuming you already staged (i.e. git add myfile1 myfile2) your files.

Blockbusting answered 22/6, 2015 at 15:13 Comment(3)
You may want to specify why creating a branch is preferable, in this case.Fivefinger
I do nothing yet. I think I need to know more about staging files.Braden
After doing these commands, it does put my changes in the new branch but I am still seeing the new (current) branch as "detached".Ruckman
G
5

to save your work in the detached head:

git checkout -b <new-branch-name-for-detached-head> <sha-of-the-detached-head>

and if you want to merge it to master:

git checkout master
git merge <new-branch-name-you-have-just-created>
Goldner answered 29/6, 2018 at 8:22 Comment(0)
G
0

If you are in 'detached HEAD' state because of checking out a tag (git checkout tags/<tag-name>), then you want to create a new branch to retain commits you create, by using -c with the switch command.

git switch -c <new-branch-name>
Godding answered 24/2, 2020 at 0:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.