%w(hashrockets spaceships bangbangs)

> non-optimized bits & pieces <

Interactive Git Rebase With Reword & Fixup

It is no secret that i’m a fan of interactive git rebase. It gives me the power to clean up the numerous small intermediate commits that i did so frequently while in the course of completing a feature (or bugfix). In the process, i usually do quite abit of squashing, reshuffling & rewording, such that the eventual commits i push upstream are well-organized & each commit is meaningful to the rest of the team.

Usually i use pick & squash to achieve the compressing of different commits. Recently, my coworker showed me an alternative, which uses reword & fixup. Here’s how it can be done:

1
$ git rebase -i <branch>

Instead of doing:

1
2
3
4
pick 6354612 WIP ~ monkey patched to fix bug#234.
squash 4de4f66 WIP ~ conform to recommended way of patching.
squash 3545b15 WIP ~ fixed incomplete removal of hackish patch.
squash 7000cfe WIP ~ removed the no-longer-needed :rightnow tag.

Do this:

1
2
3
4
reword 6354612 WIP ~ monkey patched to fix bug#234.
fixup 4de4f66 WIP ~ conform to recommended way of patching.
fixup 3545b15 WIP ~ fixed incomplete removal of hackish patch.
fixup 7000cfe WIP ~ removed the no-longer-needed :rightnow tag.

Of course, the 2 approaches are different:

  • reword & fixup, u get to either keep the 1st commit message, or rephrase it
  • pick & squash, u have more choices ~ from keeping all of the various commit messages, to writing a brand new message

For me, i almost always want the effect of reword & fixup.

Module#attr_accessor & Friends

Have u ever find urself writing simple reader & writer like this:

1
2
3
4
5
6
7
8
class Thing
  def size=(size)
    @size = size
  end
  def size
    @size
  end
end

You should probably be using Module#attr_accessor:

1
2
3
4
5
6
7
class Thing
  attr_accessor :size
end

t = Thing.new
t.size = :xl
puts t.size # >> xl

If u want to keep the writer private, while still having the reader as public, you can do the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Thing
  attr_accessor :size
  private :size=

  def cheat(size)
    self.size = size
  end
end

t = Thing.new
#puts t.size = :xl # >> NoMethodError
t.cheat(:xl)
puts t.size        # >> xl

Besides Module#attr_accessor, we also have Module#attr_reader & Module#attr_writer, each generating just the reader/writer that u need.

Using the above accessor generators not only improve the readability of ur code, the generated accessors are also more performant. Here’s a quick benchmark:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class AA
  attr_accessor :size
end

class BB
  def size        ; @size        ; end
  def size=(size) ; @size = size ; end
end

require 'benchmark'
Benchmark.bm do |x|
  [AA, BB].each do |klass|
    x.report do
      1000000.times do
        aa = klass.new
        aa.size = 2
        aa.size
      end
    end
  end
end

#>> user     system      total        real
#>> 0.410000   0.000000   0.410000 (  0.412785)
#>> 0.450000   0.000000   0.450000 (  0.456264)

The difference is there, but it isn’t too much for just a pair of accessors. It would be more significant as the number of accessors increases. Anyway, i’ll leave it as an exercise for the reader.