Skip to content

dividedmind/overcommit

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Gem Version Build Status Code Climate

Overcommit

A gem to install and manage a configurable (but opinionated) set of Git hooks. Originally written for use at Causes.

In addition to supporting global hooks, it also allows teams to define plugins specific to a repository (installed in the .githooks directory).

Read more about overcommit on our engineering blog.

Installation

The overcommit is installed as a binary via rubygems:

gem install overcommit

You can then run the overcommit command to install hooks into repositories:

mkdir important-project
cd important-project
git init
overcommit .

overcommit also accepts a handful of arguments, which can be enumerated by running overcommit --help.

At Causes, we install all of the hooks via the --all flag. In absence of this flag, you will be given the default template. For more information, try overcommit --list-templates.

Dependencies

Some of the lints have third-party dependencies. For example, to lint your SCSS files, you're going to need our scss-lint gem:

gem install scss-lint

Other useful utilities include jshint, which can be installed via npm:

npm install -g jshint

Built-in hooks

There are two types of hooks installed by this utility. post-checkout, post-merge, and prepare-commit-msg are all simple shell scripts rolled by hand for use at Causes. We think other people may find them useful.

The second, more interesting type is the Ruby-based, extensible checks. These are currently pre-commit and commit-msg. These are used for checking the validity of the code to be committed and checking the content of the commit message, respectively.

You can see the various sub-hooks available in the lib/overcommit/plugins directory:

>> tree lib/overcommit/plugins
lib/overcommit/plugins
├── commit_msg
│   ├── change_id.rb
│   ├── hard_tabs.rb
│   ├── release_note.rb
│   ├── russian_novel.rb
│   ├── single_line_subject.rb
│   ├── text_width.rb
│   └── trailing_period.rb
└── pre_commit
    ├── author_name.rb
    ├── causes_email.rb
    ├── coffee_lint.rb
    ├── css_linter.rb
    ├── haml_style.rb
    ├── haml_syntax.rb
    ├── js_console_log.rb
    ├── js_syntax.rb
    ├── python_flake8.rb
    ├── restricted_paths.rb
    ├── ruby_style.rb
    ├── ruby_syntax.rb
    ├── scss_lint.rb
    ├── test_history.rb
    ├── whitespace.rb
    └── yaml_syntax.rb

Most of them are straightforward lints, with an easter egg or two thrown in for good measure. Because some of these are Causes-specific (for instance, we insert a 'Change-Id' at the end of each commit message for Gerrit code review), the default installation will skip loading some of these checks.

Repo-specific hooks

Out of the box, overcommit comes with a set of hooks that enforce a variety of styles and lints. However, some hooks only make sense in the context of a given repository.

At Causes, for example, we have a repository for managing our Chef cookbooks. Inside this repository, we have a few additional lints we run before commits are pushed:

>> tree .githooks
.githooks
└── pre_commit
    ├── berksfile_source.rb
    ├── cookbook_version.rb
    └── food_critic.rb

food_critic.rb contains a subclass of HookSpecificCheck that runs Foodcritic against the cookbooks about to be committed (if any).

The meat of it looks like this:

module Overcommit::GitHook
  class FoodCritic < HookSpecificCheck
    include HookRegistry
    COOKBOOKS = 'cookbooks'
    @@options = { :tags => %w[~readme ~fc001] }

    def run_check
      begin
        require 'foodcritic'
      rescue LoadError
        return :stop, 'run `bundle install` to install the foodcritic gem'
      end

      changed_cookbooks = modified_files.map do |file|
        file.split('/')[0..1].join('/') if file.start_with? COOKBOOKS
      end.compact.uniq

      linter = ::FoodCritic::Linter.new
      review = linter.check(changed_cookbooks, @@options)
      return (review.warnings.any? ? :bad : :good), review
    end
  end
end

Other functionality

In addition to the Ruby-based plugin system, overcommit also ships with a few handy shell scripts:

  • post-checkout runs ctags after checkouts to aid in tag-based navigation. We use this in combination with Vim by adding .git/tags to the tags configuration:

      set tags=.git/tags,.tags
    
  • post-merge checks for updated submodules and prompts you to update them.

  • prepare-commit-msg sets up your commit message to include additional author information and note submodule changes when updating.

Uninstallation

If you'd like to remove the hooks from a repository, just pass the --uninstall flag:

overcommit --uninstall important-project

Contributing

Pull requests and issues are welcome. New features should ship with tests so that we can avoid breaking them in the future.

License

Released under the MIT License.

About

The opinionated Git hook manager

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 88.4%
  • Ruby 9.7%
  • Shell 1.9%