Coming from Sourcesafe, I have primarely been using git as a major undo feature. I tend to
work in the master branch, code happily away for some time, commit here and there and move on.
While I’m coding my brains out, I sometimes wish to drop what I’m doing right
now and start working on another feature. I know I can start another branch right now but let’s assume I’d like to keep working on master. I should have branched when
I started working on the previous feature but that would have required me to plan ahead (at which I’m terrible btw).
I am pretty confident that what I need is possible with git, but I can’t get my head
around it. As a picture tells more than a thousand words, schematicly this is what I would like to do:
0--1 master
0--1--2 master
0--1--2--3 master
0--1--2--3 aBranch
\-4 master
0--1--2--3 aBranch
\-4--5 master
Edit: I should clear up that every number is a commit.
Yes, this is possible, and not hard. The short version:
git branch aBranchto create the new branch,git stashto save any uncommitted changes, andgit reset --hard 1to resetmasterto the commit you would like, and optionallygit stash popto apply those uncommitted changes to your current working copy, if they were intended for the newmasterbranch.Here’s a full explanation, with diagrams so you can follow along. In the following, I will notate the current branch (HEAD) with a
*.Create new branch
aBranchpointing at the current commit:If you have any changes in the working copy that haven’t yet been committed, save them with a stash (this is important, as
git reset --hardwill wipe away any uncommitted changes you have):0--1--2--3 *master aBranch \- 4 stashNow reset
masterback to the revision you want it at. I’m using1below as a placeholder; you may want to use the SHA-1, or something likeorigin/masterif you want to reset it to the revision that the upstreammasterbranch was at before you made your commits:0--1--2--3 aBranch \ \- 4 stash \- *masterIf you had uncommitted changes in your working copy that you stashed away, and you want to apply them to
master, you can usegit stash applyorgit stash pop(applywill leave the stash recorded as a commit;popwill clean up the stash).Now you’re on
master, and reset to commit 1, exactly as you wanted to be. New commits will go to themasterbranch.0--1--2--3 aBranch \-4 *master 0--1--2--3 aBranch \-4--5 *masterNote that if your working copy is clean (nothing reported by
git status), you don’t need thegit stashcommand. If you wanted to apply your changes toaBranchinstead ofmaster, you would just usegit stash popthe next time you switched back toaBranchand started working on it again.One important point to keep in mind is that you should only edit branch history like this in your own private repositories, not public ones that other people could pull from. If you push this to a public repository that people are pulling from, then they’ll have to rebase all of their changes, and it’s best not to make them do that unless absolutely necessary.