OMG My Master Is My Feature Branch

Here’s a little bit of best practice for you. Whenever you start a new git repo, immediately:

  • Create a README or somesuch
  • Push that to master
  • Start immediately on a feature branch

This will allow every code change you make to be code reviewed.

As discussed in the bootstrap problem. The next step should probably be to make the project boilerplate, probably on a feature branch, and get that reviewed and merged into your master too.

Once you’re in the rhythm of code review of small increments, then everything is easier.

Yes… but I’ve already dumped loads of commits to master

Oh dear. That’s a shame. You probably want to know how you can convert your master full of commits back into a feature branch. You’re going to have to face the problem that you can’t rebase back beyond the first commit.

Here’s an example project, I messed up:

As you can see, my three commits are on master and would better be converted into a single commit on a feature branch for review against it.

Let’s look at how to do this.

First we need to create a new root

A new branch, with no previous commit is the answer. Assuming you’re in the working directory of your git repo:

# create a new orphaned branch
git checkout --orphan replaceMaster

# wipe all of the files from wherever we happened to be
git rm -rf *

# create the README we should have had all along
echo "Empty repo" > README
git add README
git commit -m "Initial empty commit"

# put this branch into the upstream
git push --set-upstream origin replaceMaster

At this point, you could look at your upstream git repository to see that you now appear to have a new root with a single commit in it.

Then we create the Feature Branch we should have had all along

This is no different to any other feature branch creation:

# assuming we're still on the replaceMaster branch
git checkout -b FeatureBranch

And into this branch we’re now going pull all the commits from master

# bring all changes from master's HEAD into a directory called `fromMaster`
git subtree add --prefix "fromMaster" origin/master

# now move all of those changes into the root folder
git mv fromMaster/* .

# and then commit this
git commit -m "Incorporating the tree"

# and let's push it
git push --set-upstream origin FeatureBranch

Where are we?

At this point, we now have:

  • master – unchanged
  • replaceMaster – a fresh branch with a single commit
  • FeatureBranch – a branch based on replaceMaster which has the new initial commit in it too

We need to:

  • Replace master with replaceMaster
  • Rewrite the history of FeatureBranch to be a nice single commit

Easy!

Finish It!

# go to the `replaceMaster` branch and push it over origin master!!!
# this is the first time you risk losing data
git checkout replaceMaster
git push origin HEAD:master -f

# now the master in the origin has been replaced
git checkout FeatureBranch
git rebase -i origin/master

# this will present you with the list of commits that have arisen since
# you created the FeatureBranch - squash them by `pick` on the first and
# `s` on the rest

# push the rebased branch up
git push -f

At this point, a simple PR from FeatureBranch to your master will allow you to review your code as though you’d created an empty master and then done everything on a Feature Branch.

Back Up

Don’t follow the above steps without taking precautions…

If it goes wrong, then you can undo the above at any time by:

# assuming you're in the git repo directory and you didn't mess
# with your copy of the master branch
# go to your original master
git checkout master

# push it back over the remote master
git push origin HEAD:master -f

Don’t Forget Your Master

Now your origin’s master has changed, maybe you want to sync your local master against it:

git checkout master
git reset --hard origin/master

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s