私たちの会社には巨大なコードベース(> 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
前もって感謝します。
これまでに行った実装には利点があります。他のブランチでステージングされていない変更をチェックするなど、考えられるエッジケースをいくつか省略していますが(最初に追加/スタッシュすることをお勧めします)。これに代わる方法は、Jenkinsのような継続的インテグレーションシステムを使用して更新を処理することです。
https://wiki.jenkins-ci.org/display/JENKINS/Meet+Jenkins
これには、gitフックシステムに比べていくつかの利点があります。これは一元的に制御できます(エンジニアが追加した複雑さを増したさまざまなオペレーティングシステムでgit-hookを機能させる際に問題が発生しました)。より多くの機能も利用できます(ユーザーが提供したモジュールがたくさんあります)。リポジトリスクリプトは、リポジトリのステータスについてJenkinsに連絡し、それに応じて更新できるようになりました。