---
title: Git to the source
teaser: Find the original commit that introduced a line of code.
tags: git
author: Ian C. Anderson
published_on: 2015-10-07
---

In a legacy software project with a long and storied history, it can be
difficult to determine why a given class, method, or line was added in the first
place.

The `git blame` command is a common tool for uncovering the history of a file on
a line-by-line basis. However, if a section of code was moved over from a
different file, the results from `git blame` can be less than useful.

Let's say I'm trying to get to the original commit message relating to code in a
method called `#fulfill`:

<kbd>git blame app/models/subscription_fulfillment.rb</kbd>

    ad36d88b (Ian 2015-09-25  1) class SubscriptionFulfillment
    ...
    ad36d88b (Ian 2015-09-25  6)   def fulfill
    ad36d88b (Ian 2015-09-25  7)     ActiveRecord::Base.transaction do
    ad36d88b (Ian 2015-09-25  8)       subscription = Subscription.create!(subscription_params)
    ad36d88b (Ian 2015-09-25  9)       UserRole.create!(user: current_user, role_type: UserRole::SUBSCRIBER)
    ad36d88b (Ian 2015-09-25 10)       BillingSchedule.create!(user: current_user, subscription: subscription)
    ad36d88b (Ian 2015-09-25 11)     end
    ad36d88b (Ian 2015-09-25 12)   end
    ...
    ad36d88b (Ian 2015-09-25 17) end

Let's look at the commit provided by the blame command:

<kbd>git show ad36d88b</kbd>

    commit ad36d88b8eabf76e70af1f47fa9f82ac0a2959f8
    Author: Ian C. Anderson <iancanderson@thoughtbot.com>
    Date:   Fri Sep 25 11:42:22 2015 -0400

        Refactor to SubscriptionFulfillment class

    diff --git a/app/controllers/subscriptions_controller.rb b/app/controllers/subscriptions_controller.rb
    index 10c7632..12dca61 100644
    --- a/app/controllers/subscriptions_controller.rb
    +++ b/app/controllers/subscriptions_controller.rb
    @@ -1,9 +1,5 @@
     class SubscriptionsController < ActionController::Base
       def create
    -    ActiveRecord::Base.transaction do
    -      subscription = Subscription.create!(subscription_params)
    -      UserRole.create!(user: current_user, role_type: UserRole::SUBSCRIBER)
    -      BillingSchedule.create!(user: current_user, subscription: subscription)
    -    end
    +    SubscriptionFulfillment.new(subscription_params).fulfill
       end
     end
    diff --git a/app/models/subscription_fulfillment.rb b/app/models/subscription_fulfillment.rb
    new file mode 100644
    index 0000000..40c2a43
    --- /dev/null
    +++ b/app/models/subscription_fulfillment.rb
    @@ -0,0 +1,21 @@
    +class SubscriptionFulfillment
    +  def initialize(subscription_params)
    +    @subscription_params = subscription_params
    +  end
    +
    +  def fulfill
    +    ActiveRecord::Base.transaction do
    +      subscription = Subscription.create!(subscription_params)
    +      UserRole.create!(user: current_user, role_type: UserRole::SUBSCRIBER)
    +      BillingSchedule.create!(user: current_user, subscription: subscription)
    +    end
    +  end
    +
    +  private
    +
    +  attr_reader :subscription_params
    +end

This doesn't give us a useful commit message about the code's origin, since this
commit simply moved the code out of a controller action into a separate
SubscriptionFulfillment class. At this point, we could run `git blame` on the
SubscriptionsController to follow back to the original commit. But in a legacy
application, this can lead you on a wild goose chase. Luckily there's a better
way!

<kbd>git blame -C app/models/subscription_fulfillment.rb</kbd>

    ad36d88b app/models/subscription_fulfillment.rb      (Ian 2015-09-25  1) class SubscriptionFulfillment
    ad36d88b app/models/subscription_fulfillment.rb      (Ian 2015-09-25  2)   def initialize(subscription_params)
    ad36d88b app/models/subscription_fulfillment.rb      (Ian 2015-09-25  3)     @subscription_params = subscription_params
    ad36d88b app/models/subscription_fulfillment.rb      (Ian 2015-09-25  4)   end
    ad36d88b app/models/subscription_fulfillment.rb      (Ian 2015-09-25  5)
    ad36d88b app/models/subscription_fulfillment.rb      (Ian 2015-09-25  6)   def fulfill
    ac97cf4a app/controllers/subscriptions_controller.rb (Kat 2014-05-05  7)     ActiveRecord::Base.transaction do
    ac97cf4a app/controllers/subscriptions_controller.rb (Kat 2014-05-05  8)       subscription = Subscription.create!(subscription_params)
    ac97cf4a app/controllers/subscriptions_controller.rb (Kat 2014-05-05  9)       UserRole.create!(user: current_user, role_type: UserRole::SUBSCRIBER)
    ac97cf4a app/controllers/subscriptions_controller.rb (Kat 2014-05-05 10)       BillingSchedule.create!(user: current_user, subscription: subscription)
    ac97cf4a app/controllers/subscriptions_controller.rb (Kat 2014-05-05 11)     end
    ac97cf4a app/controllers/subscriptions_controller.rb (Kat 2014-05-05 12)   end
    ad36d88b app/models/subscription_fulfillment.rb      (Ian 2015-09-25 13)
    ad36d88b app/models/subscription_fulfillment.rb      (Ian 2015-09-25 14)   private
    ad36d88b app/models/subscription_fulfillment.rb      (Ian 2015-09-25 15)
    ad36d88b app/models/subscription_fulfillment.rb      (Ian 2015-09-25 16)   attr_reader :subscription_params
    ad36d88b app/models/subscription_fulfillment.rb      (Ian 2015-09-25 17) end

By providing the `-C` option to `git blame`, git shows us the original commits
that added those lines, even if they were originally added to a different file.

Then we can directly view the original commit to get some more context around
the code:

<kbd>git show ac97cf4</kbd>

    commit ac97cf4a8ef12650bbcd80e93f0d45f01675574a
    Author: Kat <kat@example.com>
    Date:   Mon May 5 11:34:51 2014 -0400

        User subscribes to our service

        When a user subscribes to our super-stealth SaaS app,
        - Create their Subscription record
        - Give the user subscriber rights by assigning them a UserRole
        - Kick off recurring billing by creating a related BillingSchedule

    diff --git a/app/controllers/subscriptions_controller.rb b/app/controllers/subscriptions_controller.rb
    new file mode 100644
    index 0000000..10c7632
    --- /dev/null
    +++ b/app/controllers/subscriptions_controller.rb
    @@ -0,0 +1,9 @@
    +class SubscriptionsController < ActionController::Base
    +  def create
    +    ActiveRecord::Base.transaction do
    +      subscription = Subscription.create!(subscription_params)
    +      UserRole.create!(user: current_user, role_type: UserRole::SUBSCRIBER)
    +      BillingSchedule.create!(user: current_user, subscription: subscription)
    +    end
    +  end
    +end

This option can be particularly useful when investigating a file that has been
partially moved from a previous file, e.g. breaking up a Rails routes file, or
code refactoring and extractions like the above example.
