Letharion
Letharion

Reputation: 4229

How do I "move" my commits from "no branch" to an actual branch?

I made a mistake, and started making commits "to the last tag", which lands my commits in "no branch". They should have been applied at the head of an already existing branch. I have not pushed my changes yet. I've found a few other question for when commits are in the wrong branch, but now I have no branch, so I don't know how to handle this.

Preferably, I would like to erase my mistake entirely, and "move" my changes to the end of the right branch. If I must leave my mistake in the history, I need to merge them in atleast.

Upvotes: 45

Views: 48040

Answers (7)

questionto42
questionto42

Reputation: 9562

Not sure why this was not answered up to now. If you want to replace the actual branch with a detached HEAD (no-branch), you need to make that no-branch a temporary branch at first, as in the other answers. And then you need to overwrite everything you have in your actual branch by resetting it to the master (to get rid of all the work in the actual branch and start from new). Then merge the temporary branch into your actual branch.

git checkout choose_the_latest_commit_you_want_to_put_into_tmp
git branch tmp
git checkout the_branch_you_want_to_replace_with_tmp # (= actual branch in question)
git reset --hard master
git merge tmp
git branch -d tmp

If you make a mistake, you can always get the earlier work back by checking out the earlier id in git reflog.

Upvotes: 0

Ted van Gageldonk
Ted van Gageldonk

Reputation: 51

To offer yet another solution, you can do this with a form of rebasing (which I believe will be the most accurate answer to your actual question). This solution will actually move the commits from one place to the other, no merging.

As always with a rebase, the command includes references not to commits but to parents of commits. For instance, a simple rebase of a feature branch on top of a master branch with “$ git rebase master” is a shorthand for “$ git rebase master feature”, meaning, “take the commit that master and feature have in common, consider that commit as the old parent commit, and replace that old parent commit by the new parent commit; namely the head of master.” The automatic consequence is the moving of commits from one branch to the other. This basic scenario shows you why rebasing is concerned with parents of commits, and not with ‘moving commits around’. (I hope this helps as an introduction to what follows.)

For your situation the solution is similar in its logic, but the command involves the —onto flag and uses commit hashes instead of branch names. (This is quite identical, as branches just point to commits.) If you identify the commit hash of the commit that you branched off of (say sha1), that will be the ‘old parent’. The new parent will be the commit hash that is the head of your branch that you mention; let’s call this sha2. Then the solution to your problem is

$ git rebase —onto sha2 sha1

Which replaces the old parent by the new parent, which essentially takes the commits to the branch that you want them.

Until here your question is basically answered, as this moves the commits, but with this solution you’ll still be in detached head state. For those final steps there are many different approaches. I’d suggest to use $ git checkout -b temp; $ git checkout yourbranch; $ git merge temp; $ git branch -D temp;

The final steps are not that interesting, but I urge everyone to have a solid understanding of the git rebase —onto command. It’s the essence of the problem, and an invaluable skill for the future :)

Upvotes: 1

Nathan Buesgens
Nathan Buesgens

Reputation: 1445

Another solution, which does not involve creating a temp branch, is described here. You just merge with you last commit rather than a temp branch.

$ git checkout master
$ git merge d2bdb98

If you don't know what commit you are on you can find it with git log. I don't know if this solution is different than "cherry-picking" but it had the expected results for me.

Upvotes: 7

mpontillo
mpontillo

Reputation: 13947

I just had a situation where I had a master branch I wanted to commit to, but accidentally committed to a detached HEAD (note, the commit hash is not important here, but just to illustrate the situation):

$ git branch
* (detached from 29d2cfb)
  master

Here was my quick fix:

$ git branch -f master HEAD
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

Piece of cake.

Note that this trick only works if master originally pointed to the same commit you made your mistaken commit on top of. If that's not the case, you'll have to rebase (or cherry-pick, or merge...).

Upvotes: 2

VonC
VonC

Reputation: 1325137

Note: you have also

enter image description here

In both case, doing a tmp branch and merging it back to the actual branch is the solution.

Upvotes: 8

Sailesh
Sailesh

Reputation: 26207

You can view all your commits using git reflog

So you can simply got to another branch, and do git cherry-pick <commit-hash> for the required commits.

But I'd prefer the branch way as spatz mentioned.

Upvotes: 22

drrlvn
drrlvn

Reputation: 8437

You are currently in a detached HEAD state. To resolve that, all you need to do is create a new branch with git branch <branchname> or git checkout -b <branchname>. That will leave you with a local branch you can play with, and even delete when you're done with it.

Branches in git are just pointers to commits, so if you create a new branch where you are the new branch will point to your current commit, and then you can merge it or whatnot.

Your "mistake" need not be erased, you simply created new commits on top of previous ones. You did not modify history or anything like that.

EDIT: In response to your comment, what you need to do is:

git branch temp
git checkout master # or any other branch
git merge temp
git branch -d temp

Upvotes: 80

Related Questions