The thing to understand here is that branches in Git are not things. They aren’t places, or collections of commits, or histories. They are just names. A branch is a name that is currently attached to some commit; and it is movable, so it can be attached to some other commit, as desired. To "make a branch" just creates a name and points it — by default to where we are right now.
And HEAD
is an even simpler name; it just points (usually) at the branch name where you are working.
So, as already explained in a comment: you have
1 -- 2 -- 3 -- 4 -- 5 -- 6 -- 7 -- 8 <- main <- HEAD
So main
is pointing at 8, and we are at 8. So now say git branch branchA
. Now you have
1 -- 2 -- 3 -- 4 -- 5 -- 6 -- 7 -- 8 <- main <- HEAD, branchA
with both branch names pointing to 8. Note that you are still on main
; you didn't checkout branchA
so HEAD
still points to main
.
Since branchA
now looks exactly the way you want it to, you can now just move main
by saying git reset --hard HEAD~3
. That simply lifts the main
pointer and moves it, and so it gives:
main <- HEAD
|
v
1 -- 2 -- 3 -- 4 -- 5 -- 6 -- 7 -- 8 <- branchA
But that is topologically identical to what you want:
1 -- 2 -- 3 -- 4 -- 5 <- main <- HEAD
\
-- 6 -- 7 -- 8 <- branchA
You are still on main
so just keep working: add-and-commit, add-and-commit.
1 -- 2 -- 3 -- 4 -- 5 -- 9 -- 10 <- main <- HEAD
\
-- 6 -- 7 -- 8 <- branchA
Meanwhile branchA
is sitting there holding your old place at 8.