Git Pro Tips

What makes a good commit message? What makes for good commit contents? I present on how to reword commits to provide context, and structure commit contents to be the most meaningful for posterity with git rebase.

OS X and Project Wide Find and Replace

Have you ever needed to perform a find and replace operation that spans across numerous files in your project? Doing this operation file by file can be tedious. Searching for an answer to this issue can be frustrating due to the involvement of many different Unix tools, each with their own flags. Some of these flags are incompatible between Linux and OS X, so it can quickly devolve into plugging in a solution, and moving on when it fails.

git rebase –autosquash

When working in a feature branch, I make some changes to a file and then commit these changes. Later on, I make some additional changes to the same file on the same lines, and I want to squash these changes into the first commit touching the file.

To find out more, check out my Coderwall Pro tip:

Rail’s Acts_as_revisable now summarizes changes

If you are a frequent reader, please congratulate me next time you see me on my first ever GiHub commit. I have been a long time user of GitHub, but I haven’t contributed anything back yet. I decided to start with the project acts_as_revisable, because I have some ideas for it that I think are useful.

The commit tonight adds a “revisable_changes” column, which records the attributes “before” and “after” values in the revision record. This data is calculated from the ActiveRecord instance method “changes”. To demonstrate:

# User.create :username => 'ben'
#[nil, "ben"]}>
# User.find(1).update_attributes :username => 'bob'
#["ben", "bob"]}>

This should serve as a good base to build summaries in a human readable format in an application. After tossing around a few different word choices to describe the changes, I decided that the better approach was to just record the data that changed in a structured format and leave it up to the implementation. Such an implementation may look something like this:

  def changes_summary do |attribute, values|
      before, after = values[0], values[1]
      if before.blank? and after
        "Added #{attribute} as #{after}"
      elsif before and after.blank?
        "Removed #{attribute} value of #{before}"
        "Changed #{attribute} from #{before} to #{after}"
    end.join('; ')

Using our user instance above, this method out return: “Changed username from ben to bob”.

Other plans for acts_as_revisable in the future include tracking associations of a model. For example, if a user has many permissions, and the permissions change, the revisable information will include the permissions for that user at that point in time. I haven’t worked out the specifics of this yet, as it could potentially generate a lot of unwanted data. I plan on parsing the data from ActiveRecord’s “reflect_on_all_associations” method to gather the associations. I will then provide a way for a user to configure which associations should, or should not be tracked. Then I will iterate through these objects using ActiveRecord hooks and somehow record the state. Either a shadow table, or by serializing the associations in a column. The trick here will be to marshal the objects back to the live data when a revert is called. More soon…