Reorganizing commits in Git branches

It may take some time digging around the Git commands to do exactly what you want. I had a situation where I've gone too far in a version branch and needed some reorganization. This is a short description of what commands I ended up running.

My situation was pretty basic and maybe typical of a beginner in Git land. I had created a single extra branch from my master branch, named after the version I was working on. “3.1” in this case. I had like 40 commits to the “3.1” branch and no changes/commits to the master branch. The problem was that the version 3.1 had been released several commits ago. I had forgotten how to work with branches and continued to commit changes in the 3.1 branch, even though they belonged to the next 3.2 version.

So here are a few commands I ended up running to fix this. My goal was to get the master branch up to date, remove the commits from 3.1 branch that actually belonged to the next version and create the new 3.2 branch with those commits.

Merging branches

First step was to get the master branch up to date with all changes currently made to 3.1 branch. This is easy:

Note that you first change to the branch that should be updated and then tell Git to merge in the commits from another branch, in this case named “3.1”.

Also, since I hadn’t made any commits to the master branch, the merge is also called “fast-forward” since all changes can just be copied onto the master branch.

Listing commits and find a specific date

Next question was where I actually released version 3.1 and thereby where the 3.1 branch should be “cut”. For this I did:

Actually, the “git show-branch” didn’t help as much as “git log”, but I kept them both here for reference. I find that Git is sometimes a bit inconsistent, like specifying the number of commits to show as “–more=20” in one case and “-20” in another case.

Using “git log” and the format specifier I found the last commit that truly belonged to 3.1. I then used the short commit name from the output (code %h, 7 hex digits) for the next step.

Removing commits from a branch

Note that I already have copied all of my commits, both before and after the release of 3.1, onto the master branch. Therefore I will not remove anything important in this step. However, in other situations I am permanently removing code changes from a branch with this command so be careful when you do it yourself.

Using the commit shortname from the previous step, the removal of all commits after a specific one can be done in a single command.

Also note that there will be no trace of the commits now removed. This was exactly what I wanted in this case. There is the “git revert” command for other scenarios (I think) where the actual change in the commit tree itself will be logged as a commit.

Since this repository is also hosted on a private server, there was an issue with pushing these changes to that server. The now changed branch (3.1) refused to be pushed. I guess this is to stop you from destroying other peoples work in that branch. Anyway, since I knew it was ok, I forced the push like:

Create a new version branch from master

This step I had done before, but for completeness my last commands were:

And off I went to continue development on the 3.2 branch.

Side note: I’m not really sure what the best practice is here regarding “leaving the master branch behind” when moving on with the 3.2 branch. Of course, once I release 3.2 I’ll repeat updating master with all 3.2 changes, but during the development the master branch is left alone in my scenario. Maybe is should be moved forward too? Something to investigate for me, or for the initiated reader to add as a comment.


Leave a Reply

Twitter: @mikeplate