Git Refactoring Commits

From OpenNMS
Jump to navigation Jump to search

About Git Rebase

One of the nice features of Git is that it lets you "rewrite history" -- you can refactor your commits in to one nice, well-documented set of patches to ease sending upstream.

For example, say you were working on a small feature, and it's one of those things you're just experimenting with and hammering out as you go along. As you feel your way around to the implementation, you may end up doing:

  • git commit -m 'initial implementation, my feature'
  • git commit -m 'changed the API, testing changes'
  • git commit -m 'found an issue'
  • git commit -m 'testing now'

In the heat of the moment, it's convenient to just do a quick one-off commit message, but when you send it upstream, you don't want all this cruft.

Note that you should never do this if you're sharing your repository and people are following your changes, or you will get very strange conflicts.

Anyways, since you want to go back and rearrange the last 4 commits, you can do:

 git rebase -i HEAD~4

This opens your editor with something like:

 pick 01d1124 initial implementation, my feature
 pick 6340aaa changed the API, testing changes
 pick ebfd367 found an issue
 pick 30e0ccb testing now
 
 # Rebase 60709da..30e0ccb onto 60709da
 #
 # Commands:
 #  p, pick = use commit
 #  e, edit = use commit, but stop for amending
 #  s, squash = use commit, but meld into previous commit
 #
 # If you remove a line here THAT COMMIT WILL BE LOST.
 # However, if you remove everything, the rebase will be aborted.
 #

To combine these, just edit the file to "squash" the last 3 commits:

 pick 01d1124 initial implementation, my feature
 squash 6340aaa changed the API, testing changes
 squash ebfd367 found an issue
 squash 30e0ccb testing now
 
 # Rebase 60709da..30e0ccb onto 60709da
 #
 # Commands:
 #  p, pick = use commit
 #  e, edit = use commit, but stop for amending
 #  s, squash = use commit, but meld into previous commit
 #
 # If you remove a line here THAT COMMIT WILL BE LOST.
 # However, if you remove everything, the rebase will be aborted.
 #

When you save, git will then ask for the new commit message, and you can make something pretty like:

 Implement My Feature
 
 My Feature is a new addition to My Code that allows doing Things in a
 Stuff-like environment without needing Real Stuff.

Example

Jeff has been working on some additions to the SMSLib project which updates the USSD support with more features. We've been using a custom-built jar but it's time to send it upstream.

He started with a git svn conversion of SMSLib's SVN repository, and then made a series of changes on top of that.

I've cloned his repository, and now I'm going to combine all of his work into a couple of commits. First, looking at the commit log, he's done 13 commits (earlier I just did a 'git log' to see where the start and stop of his work was):

 git log -U 38d4d45e8d9ba62358f0712807d383451aae0539..ec48741105a3884e31894aa854e0f657e8aad501 | grep commit
 commit ec48741105a3884e31894aa854e0f657e8aad501
 commit 447237fd279d8247f3a125624cc7a613356899cc
 commit 5e26e93a19592d8f003a53b8b8a6cf36a9eec1d7
 commit 1f6356a5cc558aabbf9807b86bcb30b1931ebdff
 commit d39c4a29cd1bc3fd12e62ce7e4b28c81320a6de1
 commit 7779a82709267f56a5a3f5586998270aee69a322
 commit 59e3ec80e3f1230338e1b3daf5bb6e6f446cf7d5
 commit c4d63d2a1e3a6c2d11341572f5b655421a3735f6
 commit 2699aa14e266e408c27057a8f6a1ffc961440003
 commit 4a3aa7e30cc40460621d8b473ac35e426fb79e7c
 commit fb70e6d4496fdba99a08d9a1406dbf7c31fc7ed2
 commit 493843f4d01fffb446f7c9c132553d9d17580d00
 commit d80ce5e3a812fe17dfa704ed4780dbff1114e5b0

Just so I have a little context, I'll rebase back to the 14th commit:

 # BEFORE
 
 pick 38d4d45 Documentation.
 pick d80ce5e Add USSDResponse class Modify sendUSSDCommand methods to return USSDResponse Parameterize sending of ESC char in sendUSSDCommand methods
 pick 493843f Add Maven 2 POM
 pick fb70e6d Lots of USSD changes. Still works the old way but ready to rework it so that USSD works more like SMS.
 pick 4a3aa7e Converted to an osgi bundle
 pick 2699aa1 USSD stuff, convert to bundle
 pick c4d63d2 Moved USSD stuff out of modem/ussd
 pick 59e3ec8 Make Service USSD method throw exceptions
 pick 7779a82 Put quotes and AT+CUSD command in sendUSSDRequest method, dummy
 pick d39c4a2 Encapsulation changes to USSDDatagram hierarchy and its consumers
 pick 1f6356a Deal with USSD responses that have embedded CRs (kind of klugey)
 pick 5e26e93 Stop passing around a String gateway ID, put sendUssdRequest onto AGateway
 pick 447237f Remove instanceof ModemGateway check from Service.sendUSSDRequest, let AGateway throw UnsupportedOperationException if not a ModemGateway.
 pick ec48741 Remove gateway cast from Service.sendUSSDRequest (doh)
 
 # Rebase d207bae..ec48741 onto d207bae
 #
 # Commands:
 #  p, pick = use commit
 #  e, edit = use commit, but stop for amending
 #  s, squash = use commit, but meld into previous commit
 #
 # If you remove a line here THAT COMMIT WILL BE LOST.
 # However, if you remove everything, the rebase will be aborted.
 #

Most of the commits are just various code-in-progress that was being tested in conjunction with development work that happened on the OpenNMS side. For convenience's sake, he also added a pom.xml and then later converted it to an OSGi bundle. Matt intends to integrate with the OSGi support that's already in SMSLib's source, so I'm going to factor this into 2 commits, 1 for the code and 1 for the pom changes. Also, I'll move the pom changes to the end of the log, and maybe when we fix the OSGi integration, that can all get turned into 1 commit as well.

 # AFTER
 
 pick 38d4d45 Documentation.
 pick d80ce5e Add USSDResponse class Modify sendUSSDCommand methods to return USSDResponse Parameterize sending of ESC char in sendUSSDCommand methods
 squash fb70e6d Lots of USSD changes. Still works the old way but ready to rework it so that USSD works more like SMS.
 squash 2699aa1 USSD stuff, convert to bundle
 squash c4d63d2 Moved USSD stuff out of modem/ussd
 squash 59e3ec8 Make Service USSD method throw exceptions
 squash 7779a82 Put quotes and AT+CUSD command in sendUSSDRequest method, dummy
 squash d39c4a2 Encapsulation changes to USSDDatagram hierarchy and its consumers
 squash 1f6356a Deal with USSD responses that have embedded CRs (kind of klugey)
 squash 5e26e93 Stop passing around a String gateway ID, put sendUssdRequest onto AGateway
 squash 447237f Remove instanceof ModemGateway check from Service.sendUSSDRequest, let AGateway throw UnsupportedOperationException if not a ModemGateway.
 squash ec48741 Remove gateway cast from Service.sendUSSDRequest (doh)
 pick 493843f Add Maven 2 POM
 squash 4a3aa7e Converted to an osgi bundle
 
 # Rebase d207bae..ec48741 onto d207bae
 #
 # Commands:
 #  p, pick = use commit
 #  e, edit = use commit, but stop for amending
 #  s, squash = use commit, but meld into previous commit
 #
 # If you remove a line here THAT COMMIT WILL BE LOST.
 # However, if you remove everything, the rebase will be aborted.
 #

After saving and quitting, git then opens the editor again with the first set of commit messages:

 # This is a combination of 11 commits.
 # The first commit's message is:
 Add USSDResponse class
 Modify sendUSSDCommand methods to return USSDResponse
 Parameterize sending of ESC char in sendUSSDCommand methods
 
 Still need to put sendUSSDCommand method on Service class.
 
 # This is the 2nd commit message:
 
 Lots of USSD changes. Still works the old way but ready to rework it
 so that USSD works more like SMS.
 
 ...
 # Author:    Jeff Gehlbach <jeffg@opennms.org>
 #
 # Not currently on any branch.
 # Changes to be committed:
 #   (use "git reset HEAD <file>..." to unstage)
 #
 #  modified:   src/java/org/smslib/AGateway.java
 #  new file:   src/java/org/smslib/IUSSDNotification.java
 #  modified:   src/java/org/smslib/Service.java
 #  new file:   src/java/org/smslib/USSDDatagram.java
 #  new file:   src/java/org/smslib/USSDDcs.java

I'll erase all that, and put in a nice high-level comment describing the feature:

 Expanded USSD support for SMSLib
 
 This patch updates and builds upon the existing USSD support in SMSLib.
 It adds support for CUSD and interactive USSD requests/responses, and
 implements reasonably complete support for common USSD operations.

And after that, I do the same for the POM commits:

 Add an OSGi pom.xml for Maven builds

If you do a git log, you'll notice that it knows that all of the commits that have been combined were from the same author, even though they are not me:

 commit 2ca6e230f816b9718016b7c8d2359778f8ffa667
 Author: Jeff Gehlbach <jeffg@opennms.org>
 Date:   Fri Aug 7 15:34:27 2009 -0400
 
     Add an OSGi pom.xml for Maven builds
 
 commit 0de056b0b8a210c2376b7c91fcb51b3940f737ff
 Author: Jeff Gehlbach <jeffg@opennms.org>
 Date:   Fri Aug 7 15:24:43 2009 -0400
 
     Expanded USSD support for SMSLib
     
     This patch updates and builds upon the existing USSD support in SMSLib.
     It adds support for CUSD and interactive USSD requests/responses, and
     implements reasonably complete support for common USSD operations.

Now you just have 2 simple patches, easy to send up-stream. All that's left to do is format patches:

 $ git format-patch HEAD~2
 0001-Expanded-USSD-support-for-SMSLib.patch
 0002-Add-an-OSGi-pom.xml-for-Maven-builds.patch
 $ head -20 0001-Expanded-USSD-support-for-SMSLib.patch 
 From 0de056b0b8a210c2376b7c91fcb51b3940f737ff Mon Sep 17 00:00:00 2001
 From: Jeff Gehlbach <jeffg@opennms.org>
 Date: Fri, 7 Aug 2009 15:24:43 -0400
 Subject: [PATCH 1/2] Expanded USSD support for SMSLib
 
 This patch updates and builds upon the existing USSD support in SMSLib.
 It adds support for CUSD and interactive USSD requests/responses, and
 implements reasonably complete support for common USSD operations.
 ---
  src/java/org/smslib/AGateway.java                  |   18 +-
  src/java/org/smslib/IUSSDNotification.java         |   41 +
  src/java/org/smslib/Service.java                   |   48 +-
  src/java/org/smslib/USSDDatagram.java              |   59 ++
  src/java/org/smslib/USSDDcs.java                   |  114 +++
  src/java/org/smslib/USSDRequest.java               |  105 ++
  src/java/org/smslib/USSDResponse.java              |  109 ++
  src/java/org/smslib/USSDResultPresentation.java    |   59 ++
  src/java/org/smslib/USSDSession.java               |  144 +++
  src/java/org/smslib/USSDSessionStatus.java         |   84 ++
  src/java/org/smslib/modem/AModemDriver.java        |   36 +-

Voila! Your commits are refactored.