Skip to content

Instantly share code, notes, and snippets.

@tuki0918 tuki0918/howto.md
Last active Jul 30, 2018

Embed
What would you like to do?
git hook 引用多めのため非公開

明日からはじめる Git フック


フックスクリプトの種類とサンプル

 

logo

参考


book

Gitポケットリファレンス

Git hooks まとめ - Qiita キータ

※ 主に上記2つの内容を多く含んでいます。

Git フック とは?


  • コミットやプッシュなどリポジトリの操作を行う前後で、行う処理のこと。  

[フック (プログラミング) - Wikipedia](http://ja.wikipedia.org/wiki/%E3%83%95%E3%83%83%E3%82%AF_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)

フック(Hook)は、プログラム中の特定の箇所に、

利用者が独自の処理を追加できるようにする仕組みである。

また、フックを利用して独自の処理を追加することを「フックする」という。

調べた目的


定期的に自動処理を挟むことで、ラク出来るんじゃないかと思った。

じゃあ、どんなことできんの?


  • 事前にテストを実行
  • コーディングスタイルの検査
  • テンプレートのコミットメッセージを使う
  • 自動でIssue番号などをメッセージに追加
  • メール通知
  • 継続的インテグレーション(CI)サーバーへの通知

✌('ω'✌ )三✌('ω')✌三( ✌'ω')✌

フックスクリプトの種類


  • クライアントサイドフック

    • コミットに関するもの ← (今回はこれについて)
  • サーバーサイドフック

    • プッシュに関するもの

コミットに関するフック処理


flow

Gitポケットリファレンス p238

フックスクリプト種類(1)


pre-commit

  • タイミング:コミットが呼ばれた直後

  • 引数:なし

  • 利用シーン

    • 事前にテストを実行
    • 行末の空白文字の検査
    • ドキュメントの検査
    • コーディングスタイルの検査

フックスクリプト種類(2)


prepare-commit-msg

  • タイミング:コミットメッセージを編集する直前

  • 引数1:コミットメッセージ格納ファイル

  • 利用シーン

    • テンプレートのコミットメッセージを使う
    • 自動でIssue番号などをメッセージに追加

※ SourceTree だと「コミットメッセージ入力画面」に反映されなかった

※ 通常は「git commit」 -> エディタ起動時(vi, vim等)に反映されている

フックスクリプト種類(3)


commit-msg

  • タイミング:コミットメッセージを編集し、エディタを終了した後

  • 引数1:コミットメッセージ格納ファイル

  • 利用シーン

    • 文字数チェック
    • チケット番号が入っているかなど

フックスクリプト種類(4)


post-commit

  • タイミング:コミット処理が終わった後

  • 引数:なし

  • 利用シーン

    • リポジトリへはまだ反映されていないが編集しているファイルがあることを他の開発者に通知するのに利用できます。

コミットを中止したい


  • pre-commit

コミットが呼ばれた直後

  • prepare-commit-msg

コミットメッセージを編集する直前

  • commit-msg

コミットメッセージを編集し、エディタを終了した後

0以外の値を返して終了させることにより、異常終了にすることができます。

※ post-commitでは、すでにコミットが完了しているので、処理を中断することはできません。

導入方法


git init

.git/hooks/

├─ applypatch-msg.sample

├─ commit-msg.sample

├─ post-commit.sample

├─ post-receive.sample

├─ post-update.sample

...

├─ prepare-commit-msg.sample

└─ update.sample

mv post-commit.sample post-commit ← ファイル名を変更

chmod +x commit-msg ← 実行権限を与える

※ .gitフォルダ内のファイルはgitで管理できないので、フックスクリプトを共有する場合は専用のフォルダを用意して各自.git/hooks/に移動しないとだめ

コード 書き方


Rubyの場合

#! /usr/bin/env ruby #(1)シェバンの記述

if can_commit? #(2)コミットできるかのチェック
    puts "#commit ok"
else
    puts "#commit failure"
    exit 1 #(3)異常終了する
end

1. シェバンの記述

./pre-commit のように実行できないといけないので、シェバンを記述します。

2. コミットできるかのチェック

can_commit? がtrueだったら、コミットができて、false だったら、コミットができないようになっています。

上記のサンプルコードを使用する場合は、can_commit?の部分を実際のコードに置き換えてください

3. 異常終了する

コミットしてはいけない場合は、exit 1で異常終了して、コミットができないことをGitに伝えないといけません。

Gitでコミット前にフックする方法 | SetucoCMSプロジェクト

使える言語


好きなシェバンでスクリプトを記述すればよい。

シェバン (shebang) 一覧

  • #!/bin/sh ← 主流
  • #!/usr/bin/env ruby ← 主流
  • #!/usr/bin/env php
  • #!/usr/bin/env perl
  • など...

特にシェルスクリプト、Rubyなどのサンプルコードが見つかる場合が多い

コード例 サンプル(1)


.git/hooks/prepare-commit-msg

コミットメッセージにブランチ番号を挿入する

$ git checkout -b 1234-hoge
$ git commit -am "modified hoge"
[1234-hoge 6f595df] [1234] modified hoge
#!/usr/bin/env ruby

current_branch = `git br | grep '*'`.chomp.sub('* ', '') #
if /^(\d+)-.*/ =~ current_branch
  commit_msgs = File.readlines(ARGV[0]) #
  open(ARGV[0], 'w') {|file|
    file.print "[#{$1}] " #
    file.puts commit_msgs
  }
end

まずは、①の部分で、現在のブランチ名を取得します。

次に、②の部分でコミットメッセージファイルの中身を読み込みます。

-mオプションでメッセージを指定している場合は、そのメッセージが入っていて、

エディタを立ち上げる場合は、デフォルトのメッセージが入ってます。

最後に③の部分で、メッセージの冒頭にチケット番号を挿入します。

Gitのコミットメッセージを書き換えるフックをRubyで書いてみる

コード例 サンプル(2)


.git/hooks/prepare-commit-msg

コミットメッセージの先頭に「yyyy/dd/mm」または「yyyy/d/m」が無ければ、今日の日付を追加する。

先頭に「yyyy/dd/mm」または「yyyy/d/m」がある場合は追加しない。

$ git commit -am "commit message"
1f9ee20 2013/12/13  commit message
#!/usr/bin/env ruby

commit_msg = File.readlines(ARGV[0])
open(ARGV[0], 'w') do |file|
	if /^\d{4}\/\d{1,}\/\d{1,}/ !~ commit_msg.first
		today = Time.now.strftime("%Y/%m/%d")
		file.puts "#{today} #{commit_msg}"
	else
		file.puts "#{commit_msg}"
	end
end

まとめ


Git フック

  • 特定のタイミングで任意の処理を行うことができる

  • 工夫次第で面倒な処理が自動化出来る

  • 好きな言語で記述出来るので、すぐ始めれる

  単純で面倒な処理、Git フックに任せてみませんか?

おわり


時間余ったら


プッシュに関するフック処理


flow

Gitポケットリファレンス p240

改善していきたいこと


Deploy : ローカルで変更した箇所をサーバー毎に手動で反映しないといけない。面倒、ミスりそう。

Test : とりあえず、不安定な箇所に部分的導入にしたい

CI : 定期的にTestが落ちてないか確認したい

Jenkinsについて


Git - Git フック : http://git-scm.com/book/ja/Git-%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA-Git-%E3%83%95%E3%83%83%E3%82%AF

git hookでできること - Qiita [キータ] : http://qiita.com/quattro_4/items/d8a8d498c9f853a445f5

Git hooks まとめ - Qiita [キータ] : http://qiita.com/khlizard/items/dfe1ec9d82c0ed5da7c6

gitコミット時にデバッグコードが含まれていないかをチェックする - Qiita [キータ] : http://qiita.com/quattro_4/items/f9e0884f2efe7e8c033a

gitのpre-commit hookを使って、綺麗なPHPファイルしかコミットできないようにする – まなドット : http://manaten.net/archives/645

git push で jenkins ビルドする - Qiita [キータ] : http://qiita.com/snaka/items/88d7669682e76be7af50

グリーはいかにしてJenkinsを導入したのか(2):JenkinsでCIすればiOSアプリのビルドは、もう面倒くさくない (1/2) - @IT : http://www.atmarkit.co.jp/ait/articles/1304/03/news011.html

Gitのフック(hook)を使って自動的にデプロイする | Smart : http://rfs.jp/server/git/git-hook-post-receive.html

Gitフックを仕込むgrunt-githooksについて紹介するよ - Qiita [キータ] : http://qiita.com/shoito/items/0cd10e14f437a0cab9a9

git pushで本番環境にデプロイ - データサイエンティストのタコ部屋 : http://www.geek.sc/archives/958

// プレゼン用UI
$('.root-pane').remove();
$('.gist.container.js-gist-container').css({'width': '100%'});
$('.column.files').css({'width': '100%'});
$('h3').each(function(){
$(this).css({
'margin-top': $('html').height()+'px',
'padding-top': '30px'
});
});
// 1ページに移動
$('html, body').animate({ scrollTop: $('h3').eq(0).offset().top }, 'fast');
var $bgWindow = $('<div class="modalWindow"/>');
$bgWindow.css({
'display': 'none',
'background-color': '#222',
'opacity': '.95',
'position': 'fixed',
'left': 0,
'top': 0,
'text-align': 'center',
'width': '100%',
'height': '100%',
'z-index': 999
});
$('body').append($bgWindow);
var $modalWindow = $('<div class="modalWindow"/>');
$modalWindow.css({
'display': 'none',
'position': 'fixed',
'left': 0,
'top': 0,
'text-align': 'center',
'width': '100%',
'height': '100%',
'z-index': 9999
});
$('body').append($modalWindow);
var $img = $('<img/>');
$img.attr('src', 'https://a248.e.akamai.net/camo.github.com/ff65bb633e2136888ba57bce642ae756a481475c/687474703a2f2f3133332e3234322e3133362e3135382f6769746875622d696d672f676974686f6f6b5f6c6f63616c666c6f772e706e67');
$img.css({'height': '80%','padding': '30px'});
$modalWindow.append($img);
// カウント数
var slide = {count: 0};
// カウント表示
var len = $('h3').length;
var $slideCount = $('<div id="count" />');
$slideCount.html('<span id="slideCount">'+(slide.count+1)+'</span> / <span>'+len+'</span>');
$slideCount.css({
'position':'fixed',
'right': '25px',
'top': '25px',
'z-index': 10000,
'color': '#fff',
'padding': '10px 15px',
'background-color': '#ccc',
'font-size': '1.5em'
});
$('body').append($slideCount);
// キーイベント:「←」prev、「→」next
$(window).keyup(function(e){
if((e.keyCode == 13 || e.keyCode == 37) && slide.count > 0) {
slide.count--;
$('#slideCount').text(slide.count+1);
$('html, body').animate({ scrollTop: $('h3').eq(slide.count).offset().top }, 'fast');
}
if((e.keyCode == 17 || e.keyCode == 39) && slide.count < len-1) {
slide.count++;
$('#slideCount').text(slide.count+1);
$('html, body').animate({ scrollTop: $('h3').eq(slide.count).offset().top }, 'fast');
}
if(e.keyCode == 88) {
$('.modalWindow').toggle();
}
});
@tuki0918

This comment has been minimized.

Copy link
Owner Author

tuki0918 commented Jan 15, 2014

javascript:(function(){var d=document;var s=d.createElement('script');s.src='https://gist.github.com/tuki0918/8438364/raw/slide.js';d.body.appendChild(s);})();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.