accidentally working on a wrongly-based branch

I have a workflow which I know is quite common:

  1. create feature branch
  2. make changes
  3. add changed files
  4. commit
  5. push to server

But the mistake I’m always making — all the dang time! — is to
forget the preliminary step:

  1. be on the master or other base branch

So I end up creating a branch off of whatever random branch I happened
to be on when I did step 1, which is wrong, and doesn’t set up
the merge I want my co-workers to review after I do step 5, and
certainly doesn’t set up the merge I want to eventually do back
to master. Today I didn’t discover the mistake until after step 5,
which was a huge nuisance to undo.

So I have two questions:

  1. What’s the right way to rescue myself from this mistake — that is, to take all the work I did in step 2, and cleanly move it to a new branch based where it was supposed to be?
  2. Is there a way to prevent this mistake in the first place?

For question 1, I suspect the canonical answer is git rebase. But I don’t even try to use it any more, partly because
it’s too hard to think about, and partly because it rarely works
for me anyway. (I think the failure mode is that it complains
about any other uncommitted files in the vicinity — and I always
have gobs of those.) So I tend to fall back on git show or git diff
followed by git apply, which always feels kind of low-level and
pedestrian, but is at least easy to think about, and usually works.

But is there something I’m missing? Is there some other
easy-to-think-about, guaranteed-to-work way of picking up a feature
branch and plopping it down with a different ancestor?
(I know about git filter-branch, but it’s even harder to think
about.)

But then my other question is, is there some nice way of just
avoiding the problem in the first place? I’m imagining a warning
that could pop up any time I try to create a new branch
branched off of something other than master (or some per-worktree
configurable “default” branch). If that feature doesn’t exist,
I think I may try adding it, because it would save me lots of
wasted time.

A branch is created on a commit-ish. It does not matter which commit-ish is currently checked out, unless you use a command in which the commit-ish defaults to HEAD. See DESCRIPTION on git branch.

The command’s second form creates a new branch head named
which points to the current HEAD, or if given. As a
special case, for , you may use “A…B” as a shortcut for
the merge base of A and B if there is exactly one merge base. You can
leave out at most one of A and B, in which case it defaults to HEAD.

The second form refers to

git branch [--track[=(direct|inherit)] | --no-track] [-f]
    [--recurse-submodules] <branchname> [<start-point>]

or in short

git branch <branchname> [<start-point>]

So, git branch dev equals to git branch dev HEAD. If the current head is not the expected start-point, the branch goes on the wrong track.

We can also use git checkout or git switch to create (and checkout) a new branch. They have the same rule that it defaults to HEAD if the start-point is omitted. And in many other git commands if a commit-ish is optional, it defaults to HEAD.

The commits you have made are preserved in git database, so don’t worry. They are safe unless you remove .git and haven’t done any back-up. After you create/edit the branch on the right start-point, you can use git cherry-pick, git rebase, or git format-patch + git am to apply these commits onto the right branch. git cherry-pick is simple. git rebase is the most powerful but a bit hard to grasp.

# find commits on the wrong branch
git log <branch>

# create a back-up branch
git branch backup <branch>

# reset the branch to the right start-point
# note that hard reset discards uncommitted changes,
# so use "git stash" to save the uncommitted changes
# or use "git worktree" to create a clean worktree for the task
git checkout <branch>
git reset <start-point> --hard

# apply the commits on the backup branch from the oldest to the youngest
git cherry-pick <commit1>
git cherry-pick <commit2>

# ...
# if there is any conflict, resolve it
# and use "git add" + "git cherry-pick --continue" to go on till the end 

Is there a way to prevent this mistake in the first place?

Remember to check and specify the start-point whenever you create a branch.

Your situation is a common issue in git workflows, and it’s good to address both how to recover from it and how to prevent it in the future.

Rescuing the Mistake

  1. Create a New Branch from the Correct Base:

First, create a new branch from the intended base branch (e.g., master).

git checkout master
git pull
git checkout -b new-feature-branch
  1. Cherry-Pick Changes:

Next, use cherry-pick to apply the commits from your incorrectly created branch to the new branch. Identify the commits you made on the wrong branch (you can use git log for this) and apply them to the new branch.

git cherry-pick <commit-sha>

Repeat this for each commit you want to transfer. This method is simpler than rebase and avoids the issue with uncommitted files.

  1. Handle Uncommitted Changes:

For any uncommitted changes in your working directory, stash them before switching branches and apply them in the new branch.

git stash
git checkout new-feature-branch
git stash pop

Preventing the Mistake

  1. Git Hooks:

You can use a pre-commit or pre-push hook in Git to warn you if you’re not on the intended base branch. This would require a bit of scripting.

Here’s a basic example of what this script might look like:

#!/bin/sh
intended_base="master"

current_branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$current_branch" != "$intended_base" ]; then
    echo "Warning: You are not on the $intended_base branch."
    exit 1
fi

Place this script in the .git/hooks/pre-commit or .git/hooks/pre-push file in your repository, and make it executable (chmod +x .git/hooks/pre-commit). This will abort the commit or push if you’re not on the master branch.

  1. Regular Checks:

Make it a habit to always check your current branch before starting new work (git branch or git status). While this relies on manual discipline, it’s a good practice to develop.

To “rescue yourself” after the facts, an alternative to @ElpieKay’s answer is to use git rebase --interactive (or -i) :

  1. run git rebase -i master (<- or whatever branch you want to be based on)

  2. check the list of commits that appear in the editor that git will open for you;
    if you need to only keep the last commits, just delete the lines you do not want to keep

  3. save and exit the editor to let git apply the actions you selected


In order to create a branch starting from another branch, git checkout has a -b argument:

# you can replace 'master' with any other branch name, tag name or commit sha
git checkout -b new-feature-branch master

(from my experience: you will quickly learn to type that argument without thinking about it)


* : if the editor that pops is vim and you are not comfortable with vim, you can set GIT_EDITOR=<whatever> to choose the editor that will open to edit that file

Leave a Comment