From d8adb07377e8e8896b0b6296789158e677518d74 Mon Sep 17 00:00:00 2001 From: Dan Croak Date: Sun, 11 Nov 2012 13:33:03 -0800 Subject: [PATCH] Add git-churn script After you commit a bug fix to a feature branch, find out if the code you changed to fix the bug is in files that change often: git-churn If the buggy code changes often, find smells and refactor them. Separate the parts that change often from the parts that don't. Conversely, avoid refactoring areas with low churn. Refactoring changes code, and with each change, you risk introducing new bugs. Example: [feature-branch][~/dev/rails-app] churn 2 app/controllers/accepts_controller.rb 2 config/database.yml 4 app/helpers/application_helper.rb 4 config/application.rb 9 spec/models/user_spec.rb 9 spec/spec_helper.rb 12 spec/requests/dashboard_spec.rb 13 spec/models/feedback_spec.rb 19 app/models/feedback.rb 21 app/models/user.rb --- .gitignore | 1 + bin/git-churn | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100755 bin/git-churn diff --git a/.gitignore b/.gitignore index ffe9657..a5cadc5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ vim/.netrwhist +!bin diff --git a/bin/git-churn b/bin/git-churn new file mode 100755 index 0000000..01062e0 --- /dev/null +++ b/bin/git-churn @@ -0,0 +1,64 @@ +#!/usr/bin/ruby +# +# Credits: Corey Haines, Gary Bernhardt, Dan Croak +# +# Put this on your $PATH (~/bin is recommended). +# +# Show churn for the files changed in the branch: +# +# $ git-churn +# + +class GitChurn + attr_accessor :all_files_with_churn_count, :changed_files, :result + + def calculate + get_all_files_with_churn_count + get_changed_files + filter_into_result + print_result + end + + private + + def get_all_files_with_churn_count + self.all_files_with_churn_count = + `git log --all #{format_logs} | #{remove_blank_lines} | #{sort_by_ascending_churn_count}`.split("\n") + end + + def format_logs + "--name-only --format='format:'" + end + + def remove_blank_lines + "grep -v '^$'" + end + + def sort_by_ascending_churn_count + 'sort | uniq -c | sort' + end + + def get_changed_files + self.changed_files = + `git log origin/master..HEAD #{format_logs} | #{remove_blank_lines} | #{remove_duplicates}`.split("\n") + end + + def remove_duplicates + 'sort | uniq' + end + + def filter_into_result + self.result = all_files_with_churn_count.select { |file| file_changed?(file) }.join("\n") + end + + def file_changed?(file) + changed_files.any? { |changed_file| file.include?(changed_file) } + end + + def print_result + puts result + end +end + +git_churn = GitChurn.new +git_churn.calculate