Restating the problem

Here, you are starting out on master, but we could pick any starting (local) branch B that has some upstream U set. (In your particular case the upstream is origin/master.) You started on a task that you thought was quick and easy, and now you have realized that it is not so quick and easy after all, so you would like to "spin it off" to its own branch.

We may observe, then, that what we want is to save the name of the current branch, then change Git's notion of "the current branch" to a newly created branch, pointing to the current commit, then adjust the saved branch to point to the saved branch's upstream.

Background

Branch names are simply labels pointing to some commit. Git is fairly sensible here: git branch lets you create a new label pointing to any existing commit, or move anything except the current branch to any existing commit. The default is to create the new branch pointing to the current commit.

The tricky part is that the current branch cannot be moved this way, and the reason for that is that the current branch must match the index and work-tree except for whatever active changes you are making right now. There is only one user-facing ("porcelain") command for changing Git's notion of "the current branch", which is git checkout.

Fortunately, git checkout also has the -b (create new branch) flag, which operates much like git branch: it defaults to creating a new branch at the current commit. Furthermore, it avoids touching the index and work-tree as much as possible—just like any other git checkout—so if we create a new branch at the current commit, it never has to touch the index or work-tree at all. The result is that it always succeeds, and leaves us on the newly created branch. (It can create a new branch pointing to a particular commit, but that can also fail—but we don't need that feature here, so we get to use the mode in which it doesn't fail. Well, "doesn't fail" as long as the new branch name really is new, at least.)

Hence, the solution

The solution still needs to be a few lines of script, but we can write this as a small script named git-spinoff and put that in our $PATH (I would use $HOME/scripts/git-spinoff for this). We could even do this as a shell alias function, but I find scripts to be better in general (easier to understand, debug, etc.).

To make this script reliable, let's actually check our required condition: that we're on some branch (so HEAD is not "detached") and that this branch has an upstream set. Then we can create our new branch and re-point—using git branch -f, i.e., without using git reset—the other branch:

#! /bin/sh
#
# git-spinoff: spin the current branch off to a new
# branch. When this succeeds, we are on the new branch.
die() {
echo "fatal: $@" 1>&2
exit 1
}
# check arguments
case $# in
1) newbranch="$1";;
*) echo "usage: git spinoff <newbranch>" 1>&2; exit 1;;
esac
# make sure we are on a branch that has an upstream
branch=$(git symbolic-ref -q --short HEAD) ||
die "existing branch is detached; there's nothing to restore"
upstream=$(git rev-parse -q --verify @{u}) ||
die "existing branch $branch has no upstream: there's nowhere to restore-to"
# now create and check out out the new branch, or quit if we can't
git checkout -b "$newbranch" || exit $?
# last, re-adjust the previous branch (which is no longer the current
# branch since we are on the new one we created) to point to its own
# upstream (if this fails, ignore the failure!)
git branch -f "$branch" "$upstream"

That last command can actually be improved, as there is a "plumbing command" that does what we want. To use it, we must retain the full (refs/heads/ style) name of the original branch, and choose a message. This particular message might be improve-able, hence is just a sample: