Atualize o super repositório do Git automaticamente quando um submódulo é atualizado

3

em nossa empresa, temos uma enorme base de código (> 100000 arquivos) e, portanto, a mantemos em vários repositórios git. Portanto, temos uma floresta de repositórios e um super repositório contendo apenas referências de submódulos sobre isso.

A idéia é ter o super repositório apenas como uma cola de conveniência e atualizá-lo automaticamente sempre que um desenvolvedor atualizar qualquer submódulo.

Eu experimentei o gancho pós-recebimento e terminei com a seguinte implementação:
(envolve git plumbing para poder modificar diretamente o repositório nu)

#!/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/ 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

Agora as perguntas são:

  • É uma boa idéia usar um gancho git para modificar outro repositório que não aquele que acionou o evento?
  • A implementação do hook é OK?
    (Parece estar funcionando na minha máquina, mas eu não tenho experiência anterior com git encanamento e então talvez eu tenha omitido alguma coisa)
  • Eu acho que há uma possibilidade de condições de corrida no caso de dois (ou mais) submódulos serem atualizados simultaneamente. É possível evitar isso de alguma forma (por exemplo, um arquivo de bloqueio)?
    (estamos usando gitolite como camada de acesso).
  • Seria melhor usar um clone do super repositório para a modificação e depois empurrar (em oposição a modificar diretamente o super repositório)?

Obrigado antecipadamente.

    
por filodej 25.03.2011 / 13:58

1 resposta

1

Existem benefícios na implementação que você fez. Embora você tenha omitido alguns casos de borda possíveis, como a verificação de alterações não preparadas em outras ramificações (você pode querer adicionar / armazenar primeiro). A alternativa para isso é usar um sistema de integração contínua como o Jenkins para lidar com as atualizações:

link

Isto tem vários benefícios sobre o sistema git hooks. Ele pode ser controlado centralmente (nos deparamos com problemas para fazer com que os git-hooks trabalhassem em diferentes sistemas operacionais que nossos engenheiros usavam, mais complexidade nós acrescentávamos). Também há mais funcionalidades disponíveis (muitos módulos contribuídos pelo usuário). Nossos scripts de repo agora entram em contato com Jenkins para o status de repo e podem atualizar de acordo.

    
por 02.10.2011 / 07:54