当子模块更新时自动更新 Git 超级存储库

当子模块更新时自动更新 Git 超级存储库

我们公司有庞大的代码库(超过 100000 个文件),因此我们将其保存在多个 git 存储库中。因此,我们有一个存储库森林和一个仅包含子模块引用的超级存储库。

这个想法是让超级存储库作为一种方便的粘合剂,每当开发人员更新任何子模块时它都会自动更新。

我已经尝试过接收后钩子并最终得到以下实现:(
它涉及 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 hook 来修改触发事件之外的其他存储库是一个好主意吗?
  • 钩子实现是否正常?
    (它似乎在我的计算机上运行正常,但我之前没有使用过 git 管道,所以也许我遗漏了一些东西)
  • 我猜想如果同时更新两个(或更多)子模块,可能会出现竞争条件。 是否有可能以某种方式防止这种情况发生(例如锁定文件)?
    (我们正在使用吉托莱特作为接入层)。
  • 使用超级存储库的克隆进行修改然后推送(而不是直接修改裸超级存储库)是否更好?

提前致谢。

答案1

您所做的实现有很多好处。尽管您忽略了一些可能的边缘情况,例如检查其他分支中未暂存的更改(您可能希望先添加/存储)。替代方案是使用 Jenkins 等持续集成系统来处理更新:

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

与 git hooks 系统相比,这有几个好处。它可以集中控制(我们在让 git-hooks 在我们的工程师使用的不同操作系统上工作时遇到了问题,我们增加了更多的复杂性)。还有更多可用的功能(大量用户贡献的模块)。我们的 repo 脚本现在联系 Jenkins 以获取 repo 状态并可以进行相应的更新。

相关内容