This contributes to the steep learning curve with Git - what's the proper way to do something? I try to address in Getting Git by showing different ways Git commands may be used.
In this case, an alias of
move was created to solve the problem of committing work to an incorrect branch. It did so by running the following commands.
MESSAGE=$(git log -1 HEAD --pretty=format:%s) git reset HEAD~ --soft git stash git checkout destination-branch git stash pop git add . git commit -m $MESSAGE
As mentioned in the replies, there are other ways to solve this problem.
Before exploring alternative solutions, I want to address the ambiguity of the problem. In order to determine the proper solution, we need to answer a few questions:
- Does the destination branch exist or does it need to be created?
- Did I commit on top of work that does not belong on the destination branch?
- How many commits did I make incorrectly?
For me, proper means using commands with side-effects so I expend the minimal effort.
By that definition, I immediately rule out the use of
stash is a helpful Git command, it is very nuanced. For example, it stashes everything in the index, but not untracked files. This may not be what you want. Maybe you just want staged changes. Maybe you do want untracked files.
There's also no need to reset the commit just to recommit it on another branch. The assumption being you want the commit as is. You just made it on the wrong branch.
Let's look at some alternative solutions.
checkout + reset
A straightforward solution is to simply create another branch from your current branch. It will have the same commit history and therefore contain the incorrect commit. This allows you to remove the commit from the current branch. Then you can checkout the new branch and complete your work.
git branch destination-branch git reset --hard HEAD~1 git checkout destination-branch
This makes the assumption that the destination branch does not exist. It also assumes all previous commits belong on the destination branch. If either of these assumptions are not true, use the
This also assumes you only made one commit incorrectly. If you made more, increase the relative reference accordingly (e.g.
Another solution is to use
cherry-pick. As noted above, cherry picking may be used when the commit histories differ or the destination branch already exists.
First, you create and checkout the destination branch. You pass the second argument to
checkout to reference a branch point since the branches don't have the same commit history. Then you can
cherry-pick the incorrect commits. Once done, you can switch back to the previous branch and reset the incorrect commits.
git checkout -b destination-branch good-reference git cherry-pick 12345 git checkout - git reset --hard HEAD~1
This assumes the destination branch does not exist. If it does, change the first command to:
git checkout destination-branch.
As with other solutions, if you made more than one commit incorrectly, you will need to run
cherry-pick for each of the incorrect commits. You may also pass
cherry-pick a range as of Git 1.7.2. For example, if
eddd21 referenced your first incorrect commit and
7e6802 referenced the last, you could run:
git cherry-pick eddd21^..7e6802. Cherry picking a range has its own nuances. I often find I just run the individual
push + reset
In some scenarios, you may be able to simply push your current branch to a remote branch of a different name. Then reset your local branch to remove the incorrect commit.
git push origin HEAD:destination-branch git reset --hard HEAD~1
This assumes you are working with remote branches. It also assumes the commit histories are the same, but it does not matter if the destination branch exists or not.
As with other solutions, adjust the relative reference used in the
reset command to remove the appropriate number of commits.
You can see why Git can be challenging to learn and use. There are at least four different solutions for this one problem. While I advocate for a solution that keeps the commands simple, I hope by demonstrating all solutions you learned when to apply each.
Want to see more every day Git scenarios? In addition to learning about core commands, the Getting Git video series also demonstrates the commands you'll use to solve every day problems with Git.
Find this interesting? Let's continue the conversation on Twitter.