What you need to know here is that a "structural branch" (I'm experimenting with this term now) is formed by the commit graph, while a git branch label is merely "pasted onto" a commit (or "points to" a single commit, if you prefer that terminology).
It sounds like you have something like this right now:
...--o--o--A--B--C--D--E <-- master
where A
through E
are the five commits that are this new experimental feature, and the earlier o
s are other commits. (Note that "time moves forward" left-to-right, i.e., the last o
commit happened before A
, and A
happened before B
, and so on.)
Let's draw the above with a kink in the line, which does not change it in any way, but makes room in the drawing for us to stick a second label on it. Then, let's stick a second label on it.
...--o--o <-- new-label
\
A--B--C--D--E <-- master
See how, if we could just swap those two labels, we'd have exactly what you asked for: master
would point to the last commit just before A
, and new-label
would point to commit E
which then "branches off master
".
We can do exactly that. There's only one caveat: if anyone else is sharing this repository, either directly or (more commonly) via push
and pull
operations, the other people only expect branch labels to "move forward": to have new commits added over time, not to have commits "taken away" by going "back in time".
If they've picked up both your new commits (A
through E
) and the action of "moving the branch label master
forward" from the last o
commit up to E
, and then you decide to "move the label backward", you must somehow tell them: "hey, guys, sorry, but I had to move the label backward in time". Then they may have to take more actions on their own to recover from this.
If nobody else has the commits yet, you're in great shape. If others might have them but are not using them, or are OK with taking actions to recover from "moving backward", then you're still in good shape.
Here's one shortest-way to achieve the trick with the labels (there are a few more equally short ways):
Add a new label pointing to commit E
:
git checkout master # if you're not already "on branch master"
git checkout -b ExpA
(this method has the advantage of leaving you "on branch ExpA
", which I assume you'd like to be).
Now that there's a second label on E
, forcibly move master
back five commits:
git branch -f master master~5
(master~5
means "move back 5 commits from where master
is now; you can use any other method to name the desired commit, which is the last o
node in the drawings above; master@{date}
as in your own answer can do the trick, for instance).
Only if you've already push
ed commits A
through E
to some central repository (here, I assume it's called origin
) on branch master
. Note that this step is at least slightly dangerous (sometimes more than slightly, if others have pushed more commits onto master
over there) and should not be done until everyone else knows about this and has agreed to it (and if you don't know what you're doing here, let someone else—someone who's in charge of the central repository origin
—do it instead):
git push -f origin master
If others have your commits and you are not allowed to "go back in time" with the labels, you'll need to "revert" stuff instead; see other StackOverflow discussions about this.