Move commits from one branch to another
Have you ever made a few commits on a branch, only to later realise that you should have been working on a topic branch (i.e. a branch specific to the task you're working on)? So long as you haven't yet shared any of these commits with anybody else, you can easily move them on to a new branch, and then remove them from your current branch.
Making the topic branch
When I decide that I'd be better off working in a topic branch, the first thing I do is commit any outstanding work. It doesn't matter if the tests aren't currently passing; we'll just undo the commit after we've switched branches.
So let's do a "WIP" (Work In Progress) commit and make the branch:
$ git add .
$ git commit -m "WIP"
$ git checkout -b some-feature
You can also make a new branch with the git branch
command, but I prefer
checkout -b
as it also switches you to the new branch immediately (whereas
git branch
will just make the new branch, leaving you on your current
branch).
Your "WIP" commit will now be stored safely at the head of the branch that you
were on and also on the new some-feature
branch.
Tip: If you're not familiar with branching, you can check that your most recent work is on the new branch before you continue:
$ git log -p some-feature
Removing commits from master
All you need to do now is to switch back to the master
branch and remove any
work that you'd rather develop on the topic branch. If the work to remove is
just your last commit you can use git reset
to roll the branch back:
$ git checkout master
$ git reset --hard HEAD^
The --hard
option tells git to set the head of the current branch to the
commit that you specify, while modifying the files on disk to match the
contents of the repository.
The HEAD^
syntax refers to the previous commit to the head of the current
branch (i.e. the last commit on the branch), so this will roll us back one
commit. You can add extra ^
characters, so HEAD^^^
will throw away three
commits.
If you want to go back more than a couple of commits you can use the tilde syntax to save some typing:
HEAD~1
is equivalent toHEAD^
HEAD~2
is equivalent toHEAD^^
HEAD~8
is equivalent toHEAD^^^^^^^^
Note: Be careful with the --hard
option to git reset
. It isn't
something to be afraid of, but you do need to make sure that you've committed
all your local changes to another branch before you run it.
Back to work...
Now we can switch back to the topic branch and carry on from where we left off.
$ git checkout some-feature
If you had some work in progress that you saved with a "WIP" commit message you
can back that commit out now, without losing the changes (they'll still be on
your filesystem). We'll use git reset
again, but without the --hard
option:
$ git reset HEAD^
All that'll do is to remove the last commit from your repository, without actually changing your files.
And there you are; all the commits that you deleted from master
are now on your topic branch.
An insurance policy
Should you make a mistake while you're fiddling around with branches and git
reset --hard
you could find yourself in a position where you've thrown a bunch
of commits away by mistake. It's unlikely but -- let's face it -- could happen.
Don't worry, Git has got your back, and you can recover lost commits
without too much trouble.