gitフックをリポジトリに置く


197

.git / hooksをプロジェクトリポジトリに配置する(たとえば、シンボリックリンクを使用する)ことは悪い習慣と見なされていますか?はいの場合、同じフックを異なるgitユーザーに配信する最良の方法は何ですか?

回答:


143

私は一般にScytaleに同意しますが、いくつかの追加の提案がありますが、個別の回答に値するほどです。

まず、適切なシンボリックリンクを作成するスクリプトを書く必要があります。特に、これらのフックがポリシーの適用または有用な通知の作成に関するものである場合は特にそうです。フックを使用する可能性bin/create-hook-symlinksは、自分で入力する必要がある場合よりも、タイプするだけの場合の方がはるかに高くなります。

次に、フックを直接シンボリックリンクすると、ユーザーが自分の個人用フックを追加できなくなります。たとえば、空白のエラーがないことを確認するサンプルのpre-commitフックが好きです。これを回避する優れた方法は、リポジトリにフックラッパースクリプトをドロップし、すべてのフックをシンボリックリンクすることです。次に、ラッパーは$0(bashスクリプトであると想定し、argv[0]それ以外は同等のものであると想定して)、呼び出されたフックを特定し、リポ内の適切なフックと、名前を変更する必要がある適切なユーザーのフックを呼び出すことができます。 、すべての引数をそれぞれに渡します。メモリからの簡単な例:

#!/bin/bash
if [ -x $0.local ]; then
    $0.local "$@" || exit $?
fi
if [ -x tracked_hooks/$(basename $0) ]; then
    tracked_hooks/$(basename $0) "$@" || exit $?
fi

インストールスクリプトは、既存のすべてのフックをサイドに移動し(.local名前に追加)、既知のすべてのフック名を上記のスクリプトにシンボリックリンクします。

#!/bin/bash
HOOK_NAMES="applypatch-msg pre-applypatch post-applypatch pre-commit prepare-commit-msg commit-msg post-commit pre-rebase post-checkout post-merge pre-receive update post-receive post-update pre-auto-gc"
# assuming the script is in a bin directory, one level into the repo
HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks

for hook in $HOOK_NAMES; do
    # If the hook already exists, is executable, and is not a symlink
    if [ ! -h $HOOK_DIR/$hook -a -x $HOOK_DIR/$hook ]; then
        mv $HOOK_DIR/$hook $HOOK_DIR/$hook.local
    fi
    # create the symlink, overwriting the file if it exists
    # probably the only way this would happen is if you're using an old version of git
    # -- back when the sample hooks were not executable, instead of being named ____.sample
    ln -s -f ../../bin/hooks-wrapper $HOOK_DIR/$hook
done

6
chmod +x .git/hooks/*はあなたbin/create-hook-symlinks にそれを働かせるために加えました。
guneysus 2014年

6
@guneysusフックは既に実行可能である必要があり(そのようにしてチェックする必要があります)、リンクには特別なアクセス許可は必要ありません。リンク先のファイルのみです。
Cascabel 2014年

13
フックディレクトリを取得するより良い方法は、HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooksです。
アーノルドダニエルズ2014年

2
私はこれに基づいてプロジェクトのフックを管理する簡単なシステムを組み立て
ELLIOTTCABLE

6
私は必需品だけを取り、それをリポジトリgithub.com/sjungwirth/githooksに
Scott Jungwirth

111

いいえ、それらをリポジトリーに配置することは問題ありません。他のユーザーにも役立つ場合は、そうすることをお勧めします。ユーザーは明示的にそれらを有効にする必要があります(たとえば、シンボリックリンクによって)。これは一方では少々面倒ですが、一方でユーザーの同意なしに任意のコードを実行することから保護します。


13
それが会社のポリシーである場合、コードは「任意」ではなく、これは必須コードであるため、追跡される別の(事前定義された)ディレクトリがないため、これはGITの制限と見なされます。通常のフックと一緒に実行
Tobias Hagenbeek

14
フックの自動配信はセキュリティの問題です。Gitが直接実行しないことをうれしく思います。チーム/会社のポリシーを適用するには、サーバー側でフックを使用するか、@ scyで説明されているようにユーザーが手動で有効にするように決定します:)
マークKコワン

4
「ユーザーの同意なしに任意のコードを実行することからユーザーを保護します」。開発者が提案(シンボリック)したい場合、フックは他の誰かによって変更され、「同意なしに任意のコード」を実行する可能性があります
MiniGod

24
MiniGod:もちろんです。十分に偏執的である場合は、フックをシンボリックリンクする代わりにコピーして、監査してから、有効にすることができます。ただし、ほとんどの(引用が必要)Gitリポジトリには、ユーザーのマシンで実行されるソースコードが含まれているため、常に変更され、監査されていないコードが実行される可能性があります。しかし、はい、あなたはポイントを持っています。;)
2015

46

現在、次のようにして、バージョン管理されているディレクトリをgitフックディレクトリに設定MY_REPO_DIR/.githooksできます。

git config --local core.hooksPath .githooks/

それでも直接強制することはできませんが、README(または何でも)にメモを追加する場合は、各開発者の側で最小限の労力が必要です。


3
viget.com/articles/two-ways-to-share-git-hooks-with-your-teamで見つけた1つのトリックは、Makefile / CMake config / whateverからオプションを設定することです。
Julius Bullinger

6

http://git-scm.com/docs/git-init#_template_directoryから、これらのメカニズムのいずれかを使用して、新しく作成された各gitリポジトリの.git / hooksディレクトリを更新できます。

テンプレートディレクトリには、作成後に$ GIT_DIRにコピーされるファイルとディレクトリが含まれます。

テンプレートディレクトリは、次のいずれかです(順番に)。

  • --templateオプションで指定された引数。

  • $ GIT_TEMPLATE_DIR環境変数の内容。

  • init.templateDir構成変数。または

  • デフォルトのテンプレートディレクトリ:/ usr / share / git-core / templates。


5

プロジェクトに保存してビルドにインストールする

他の人が答えで述べているように、フックが特定のプロジェクトに固有である場合は、それらをgitが管理するプロジェクト自体に含めます。これをさらに詳しく説明すると、単一のスクリプトまたはコマンドを使用してプロジェクトをビルドすることをお勧めします。ビルド中にフックをインストールする必要があります。

これについてもう少し詳しく知りたい場合は、gitフックの管理に関する記事を書きました。

Java&Maven

完全な免責事項。下記のMavenプラグインを作成しました。

JavaプロジェクトのMavenでビルド管理を処理している場合、次のMavenプラグインは、プロジェクト内の場所からのインストールフックを処理します。

https://github.com/rudikershaw/git-build-hook

すべてのGitフックをプロジェクトのディレクトリに配置してpom.xmlから、次のプラグイン宣言、目標、構成を含めるようにを構成します。

<build>
  <plugins>
    <plugin>
      <groupId>com.rudikershaw.gitbuildhook</groupId>
      <artifactId>git-build-hook-maven-plugin</artifactId>
      <configuration>
        <gitConfig>
          <!-- The location of the directory you are using to store the Git hooks in your project. -->
          <core.hooksPath>hooks-directory/</core.hooksPath>
        </gitConfig>
      </configuration>
      <executions>
        <execution>
          <goals>       
            <!-- Sets git config specified under configuration > gitConfig. -->
            <goal>configure</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
      <!-- ... etc ... -->
  </plugins>
</build>

プロジェクトビルドを実行すると、プラグインはgitを構成して、指定されたディレクトリからフックを実行します。これにより、プロジェクトで作業するすべての人のために、そのディレクトリにフックが効果的に設定されます。

JavaScriptとNPM

NPMには、ハスキーと呼ばれる依存関係があり、JavaScriptで記述されたフックを含むフックをインストールできます。

// package.json
{
  "husky": {
    "hooks": {
      "pre-commit": "npm test",
      "pre-push": "npm test",
      "...": "..."
    }
  }
}

その他

さらに、Pythonプロジェクトには事前コミット、Rubyプロジェクトにはオーバーコミット、Ruby またはノードプロジェクトには左フックがあります。


1
このプラグインを作成していただきありがとうございます。これにより、私の事前コミットファイルの統合が非常に簡単になりました。
Michiel Bugher


1

ComposerベースのPHPプロジェクトの場合、エンジニアに自動的に配布できます。以下はpre-commitとcommit-msgフックの例です。

hooksフォルダーを作成してから、composer.jsonに次のように入力します。

 },
 "scripts": {
     "post-install-cmd": [
         "cp -r 'hooks/' '.git/hooks/'",
         "php -r \"copy('hooks/pre-commit', '.git/hooks/pre-commit');\"",
         "php -r \"copy('hooks/commit-msg', '.git/hooks/commit-msg');\"",
         "php -r \"chmod('.git/hooks/pre-commit', 0777);\"",
         "php -r \"chmod('.git/hooks/commit-msg', 0777);\"",
     ],

その後、全員がcomposer install定期的に実行しているプロジェクトの継続中に、それらを更新することもできます。


0

これは、add-git-hook.shというスクリプトです。これは、レポジトリ内の通常のファイルとして出荷でき、スクリプトファイルにgitフックを追加するために実行できます。使用するフック(プリコミット、ポストコミット、プリプッシュなど)と、猫のヒアドキュメントのフックの定義を調整します。

#!/usr/bin/bash
# Adds the git-hook described below. Appends to the hook file
# if it already exists or creates the file if it does not.
# Note: CWD must be inside target repository

HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks
HOOK_FILE="$HOOK_DIR"/post-commit

# Create script file if doesn't exist
if [ ! -e "$HOOK_FILE" ] ; then
        echo '#!/usr/bin/bash' >> "$HOOK_FILE"
        chmod 700 "$HOOK_FILE"
fi

# Append hook code into script
cat >> "$HOOK_FILE" <<EOF

########################################
# ... post-commit hook script here ... #
########################################

EOF

このスクリプトは、実行可能なアクセス許可を持っていると意味がある場合があります。または、ユーザーが直接実行できます。これを使用して、コミットした後、他のマシンで自動的にgit-pullしました。

編集-私は尋ねられたものではなく、OPが探していたものではない、より簡単な質問に答えました。以下のコメントで、外部で管理するのではなく、リポジトリでフックスクリプトを配布するためのユースケースと引数について意見を述べました。それがあなたが探しているもの以上であることを願っています。


私はあなたの努力に感謝します、しかしここに貴重な情報があると信じています-それは述べられた質問に答えません。
shabunc

私の意見では、フックが特定のリポジトリに固有であるか、使用されるワークフローの不可欠なコンポーネントである場合、それらはファイルとしてリポジトリに属します。それが解決する以上の問題を作成することなく、それらを他の場所に配置することは困難です。一般的なフックを、それ自体のリポジトリまたは共有ドライブに保存できます。これにより、プロジェクトのリポジトリをクリーンに保つことができますが、実際的ではありません。フックは簡単に追加できる必要があると私は他のユーザーに同意します。シンボリックリンクは、特定のシステムまたはファイル構造への不要な依存関係を作成する場合があります。
mathewguest

さらに、シンボリックリンクにより、ユーザーは独自のフックを追加できなくなります。.git / hooksディレクトリは追跡されないので、ソースはリポジトリで開始し、それをフックスクリプトに入れる必要があります。逆ではありません。反論は、gitフックがプロジェクトではなくワークフローまたはチームに関連しているため、リポジトリに属していないことだと思います。特定のユースケースに応じて、関連性の低いフックでgitリポジトリを汚染する可能性があっても大丈夫ですか、それとも別の場所に配置することの複雑さの束を先に見たいですか?
mathewguest

0

pre-commitのようなpre-commitフック管理のマネージドソリューションを使用できます。または、Datree.ioのようなサーバー側のgit-hooks向けの集中型ソリューション。次のようなポリシーが組み込まれています。

  1. シークレットのマージを検出して防止ます。
  2. 適切なGitユーザー構成を適用します
  3. 強制のJIRAチケットの統合 -プル要求名に言及チケット番号を/コミットメッセージを。

すべてのフックを置き換えるわけではありませんが、すべての開発者のコ​​ンピューター/リポジトリにフックをインストールする構成の地獄なしで、最も明白なもので開発者を助けるかもしれません。

免責事項:私はDatreesの創設者の一人です


3
あなたは面白い製品を作っていると思いますが、これも質問に答えるものではなく、基本的に自己宣伝であり、それ以上のものではないと思います。
shabunc
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.