Skip to content
⚡️ Supercharged git hooks manager in pure Elixir
Elixir
Branch: master
Clone or download
edisonywh Merge pull request #16 from edisonywh/bump/0.2.0
Bump Committee from 0.1.2 to 0.2.0
Latest commit e8ff637 Oct 14, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
lib Warn instead of error if `config` is not provided Oct 14, 2019
test Initial commit Oct 6, 2019
.formatter.exs Initial commit Oct 6, 2019
.gitignore Initial commit Oct 6, 2019
LICENSE Add LICENSE Oct 7, 2019
README.md Bump Committee from 0.1.2 to 0.2.0 Oct 14, 2019
commit.exs (Meta 🚀) Remove logging line Oct 8, 2019
mix.exs Bump Committee from 0.1.2 to 0.2.0 Oct 14, 2019
mix.lock Add `ex_doc` for dependency Oct 7, 2019

README.md

Committee

Reminder: While Committee is working great for my own use-case, there can be occasional bugs every now and then, if your workflow rely heavily on a Git workflow, proceed at your own risk. Otherwise a PR is very much welcomed!


Committee is a supercharged ⚡️ git hooks manager in pure Elixir.

What does supercharged mean? This is what supercharged means.

Supercharged means:

  • You get to write code with your git hooks.
  • You get to write Elixir code with your git hooks.
  • You get to write any Elixir code with your git hooks.
  • Any. Elixir. Code. ⚡️

Read on to find out more!

Installation

Get the latest version from Hex

def deps do
  [
    {:committee, "~> 0.1.2", only: :dev, runtime: false}
  ]
end

Usage

Documentation can be also be found over on HexDocs.

After installing Committee, all you have to do is run

mix committee.install

Your existing git hooks will be backed-up and renamed from hook to hook.old

You should see a commit.exs file being generated, that's where you'll be writing your hooks.

The file should look something like this:

defmodule YourApp.Commit do
  use Committee
  import Committee.Helpers, only: [staged_files: 0]

  # ...
  # ...
  #
  # ## Example:
  #
  #   def pre_commit do
  #     System.cmd("mix", ["format"] ++ staged_files())
  #     System.cmd("git", ["add"] ++ staged_files())
  #   end
  #
  # ...
  #
end

To run code for a hook, write a function with the same name (in snake_case) as that hook. For a full list of git hooks in the wild, checkout this list over here.

To abort a commit, return in the form of {:halt, reason}. To print a success message, return in the form of {:ok, message}.

If you find that Committee does not do what you want (do let me know how to improve!) and you want to stop using it, you can run the built-in uninstallation task: mix committee.uninstall. This will restore your existing hooks backup too.

For a list of Committee supported hooks, checkout Committee.__hooks__/0 For a list of Committee provided helpers (such as staged_files/0, branch_name/0, checkout Committee.Helpers)

Currently only pre_commit and post_commit are supported, this is mostly because I haven't tested the other ones, rather than any technical limitation, but I don't see why it won't work for the others. PRs are welcomed!

What are git hooks?

If you're reading this, you're probably familiar with Git. We are all used to terms like commit, rebase, but did you know that Git ships with the ability to run a hook/callback when you run these actions?

This effectively means you can write code that gets executed when you do a git commit, or when you're commencing a rebase. Exciting innit? :)

What is Committee trying to solve?

Git hooks are great, but in my experience, there are two issues with them:

1) Hassle to set-up

I find that it's not exactly straightforward to write git hooks, here's my own flow of writing a git hook (true story):

  • read up about the amazing git hooks (like you're doing now)
  • navigate into .git/hooks
  • vim pre-commit
  • writes in bash 1
  • make pre-commit into an executable.
  • Wait, how do you make it into an exectuable?
  • googles for 5 mins
  • Ah, chmod +x pre-commit

I wanted an easier process for myself, but also read on to find out more.

2) Difficult to share with team

Git hooks live in the .git/hooks/ folder, and .git folder isn't versioned, this means that whatever you've just done in the previous step would not work for your other team members.

No biggie aye? You just have to get each and every one of your teammate to repeat step 1.

Did I also mentioned that if you decided to update the pre-commit script (for example, you have a change in branchs' naming convention), you'd have to again, convince everyone in your team to repeat step 1?

Yup.

Get yourself a Committee!

The premise of Committee is simple, it solves the aforementioned problems like so:

Hassle to set-up

Well for starters, you don't have to write any bash script1. Bash scripts are great, but wouldn't you rather write Elixir?

Also, you dont have to care about things like making a file executable. Committee will handle that for you :)

Difficult to share with team

Committee exposes an easy mix task to install itself.

To share it with your team, all you have to do is to put mix committee.install in one of your onboarding script. It's a one-time installation, and from then on, any updates you make to commit.exs (Committee's configuration file) will become immediately available to your team mates.

No fuss, no muss.

What are some alternatives?

Husky

Husky is great, it's a popular git hook manager in JavaScript-land. It is not limited to just JS, it also works for any other languages, including Elixir.

The only downside is that you'd need to set up package.json to include the husky dependency. I figured not every Elixir project would have package.json (for example when developing a library), hence Committee.

Husky is a much more battle-proven solution, and works for most scenarios (especially if you already have a package.json), so definitely go for that if suits your use case.

Lefthook

A project from Evil Martian. This project is really interesting, it is written in Go, works for any language by using a language-agnostic .yml config file. I like the idea that it's taking.

I was really contemplating using Lefthook, but I decided to take up a sort of challenge to come up with an Elixir-like hook manager, so well here we are..

Other Elixir Alternatives

There are few more Elixir-centric packages, like:

They all look great, but all hinges on using config.exs to do configuration Now that I'm writing this out, I realised I'm the outlier here.., which works, but I decided to be a little bit more creative, and take this Elixir thing a step further.

Thus born Committee, which allows you to write any Elixir code in a commit.exs file, because why not?

1 This is not always the case, you can change the shebang to run your code with other shell/languages, such as ruby.


Contributions

Contributions are very welcomed, but please first open an issue so we can align and discuss before any development begins.

License

View License

You can’t perform that action at this time.