web-dev-qa-db-ja.com

サブモジュールが更新されると、Gitスーパーリポジトリが自動的に更新されます

私たちの会社には巨大なコードベース(> 100000ファイル)があるので、それをいくつかのgitリポジトリに保存しています。したがって、リポジトリのフォレストと、その上にサブモジュール参照のみを含む1つのスーパーリポジトリがあります。

アイデアは、便利な接着剤としてスーパーリポジトリを用意し、開発者がサブモジュールを更新するたびに自動的に更新することです。

post-receiveフックを試してみたところ、次の実装になりました。
(ベアリポジトリを直接変更できるようにするためにgit配管が必要です)

#!/bin/bash -e

UPDATED_BRANCHES="^(master|develop)$"
UPDATED_REPOS="^submodules/.+$"

# determine what branch gets modified
read REV_OLD REV_NEW FULL_REF
BRANCH=${FULL_REF##refs/heads/}

if [[ "${BRANCH}" =~ ${UPDATED_BRANCHES} ]] && [[ "${GL_REPO}" =~ ${UPDATED_REPOS} ]];
then
    # determine the name of the branch in the super repository
    SUPERBRANCH=$FULL_REF
    SUBMODULE_NAME=${GL_REPO##submodules/}
    # clean the submodule repo related environment
    unset $(git rev-parse --local-env-vars)
    # move to the super repository
    cd $SUPERREPO_DIR

    echo "Automaticaly updating the '$SUBMODULE_NAME' reference in the super   repository..."
    # modify the index - replace the submodule reference hash
    git ls-tree $SUPERBRANCH | \
        sed "s/\([1-8]*\) commit \([0-9a-f]*\)\t$SUBMODULE_NAME/\1 commit $REV_NEW\t$SUBMODULE_NAME/g" | \
        git update-index --index-info

    # write the tree containing the modified index
    TREE_NEW=$(git write-tree)
    COMMIT_OLD=$(git show-ref --hash $SUPERBRANCH)

    # write the tree to a new commit and use the current commit as its parent
    COMMIT_NEW=$(echo "Auto-update submodule: $SUBMODULE_NAME" | git commit-tree $TREE_NEW -p $COMMIT_OLD)

    # update the branch reference
    git update-ref $SUPERBRANCH $COMMIT_NEW
    # shall we also update the HEAD?
    # git symbolic-ref HEAD $SUPERBRANCH
fi

今の質問は次のとおりです。

  • イベントをトリガーしたリポジトリとは別のリポジトリを変更するためにgitフックを使用することはまったく良い考えですか?
  • フックの実装は大丈夫ですか?
    (私のマシンでは動作しているようですが、git配管の経験がないため、何かを省略している可能性があります)
  • 2つ(またはそれ以上)のサブモジュールが同時に更新された場合、競合状態になる可能性があると思います。どういうわけかそれを防ぐことは可能ですか(例えば、ロックファイル)?
    (アクセスレイヤーとして gitolite を使用しています)。
  • スーパーリポジトリのクローンを変更に使用してからプッシュする方がよいでしょうか(ベアスーパーリポジトリを直接変更するのではありません)。

前もって感謝します。

3
filodej

これまでに行った実装には利点があります。他のブランチでステージングされていない変更をチェックするなど、考えられるエッジケースをいくつか省略していますが(最初に追加/スタッシュすることをお勧めします)。これに代わる方法は、Jenkinsのような継続的インテグレーションシステムを使用して更新を処理することです。

https://wiki.jenkins-ci.org/display/JENKINS/Meet+Jenkins

これには、gitフックシステムに比べていくつかの利点があります。これは一元的に制御できます(エンジニアが追加した複雑さを増したさまざまなオペレーティングシステムでgit-hookを機能させる際に問題が発生しました)。より多くの機能も利用できます(ユーザーが提供したモジュールがたくさんあります)。リポジトリスクリプトは、リポジトリのステータスについてJenkinsに連絡し、それに応じて更新できるようになりました。

1
polynomial