Dizer se um commit git é um compromisso de mesclagem/reverter
-
26-09-2019 - |
Pergunta
Estou escrevendo um script que exige verificar se uma confirmação específica é uma confirmação de mesclagem/reversão ou não, e estou me perguntando se há um truque git para isso.
O que eu criei até agora (e definitivamente não quero depender da mensagem de confirmação aqui) é verificar HASH^2
E veja se eu não recebo um erro, existe uma maneira melhor?
Solução
Descobrir se algo é uma mesclagem é fácil. Tudo isso é cometido com mais de um pai. Para verificar isso, você pode fazer, por exemplo
$ git cat-file -p $commit_id
Se houver mais de uma linha "pai" na saída, você encontrou uma mesclagem.
Para reverte, não é tão fácil. Geralmente, os revertidos são apenas commits normais que aplicam o diferencial de um compromisso anterior no reverso, removendo efetivamente as alterações que se comprometem introduzidas. Não há especial de outra forma.
Se uma revertia foi criada com git revert $commit
, então o Git geralmente gera uma indicação de mensagem de confirmação na revertência e o que o comprometeu revertido. No entanto, é bem possível reverter de outras maneiras, ou apenas alterar a mensagem de confirmação de uma confirmação gerada por git revert
.
Procurar aqueles que gerados revertem mensagem de compromisso já podem ser uma heurística suficientemente boa para o que você está tentando alcançar. Caso contrário, você teria que realmente examinar outras confirmações, comparando suas diferenças entre si, olhando de uma é a operação reversa exata de outra. Mas mesmo essa não é uma boa solução. Muitas vezes, os revertidos suficientes são um pouco diferentes do que apenas o reverso da confirmação que eles estão revertindo, por exemplo, para acomodar as alterações de código que ocorreram entre a confirmação e a revertência.
Outras dicas
A seguinte instrução será despejada só os hashes dos pais. Menos filtragem necessária ...
git show --no-patch --format="%P" <commit hash>
A resposta usando git cat-file
está usando um git "encanamento" O comando, que geralmente é melhor para criar scripts, pois é provável que o formato de saída não mude. Os que usam git show
e git rev-parse
pode precisar mudar com o tempo enquanto eles estão usando porcelana comandos.
A função bash que eu uso há muito tempo usa git rev-list
:
gitismerge () {
local sha="$1"
msha=$(git rev-list -1 --merges ${sha}~1..${sha})
[ -z "$msha" ] && return 1
return 0
}
A lista de comandos de porcelana/encanamento pode ser encontrada nos documentos para o nível superior git comando.
Este código usa Git-Rev-List com um específico Gitrevisões consulta ${sha}~1..${sha}
De uma maneira que imprime o segundo pai de um SHA, se ele existir, ou nada se não estiver presente, que é a definição exata de uma confirmação de mesclagem.
Especificamente, SHA~1..SHA
significa Inclua commits acessíveis da SHA, mas excluem aqueles que são acessíveis SHA ~ 1, que é o primeiro pai do SHA.
Os resultados são armazenados em $ msha e testados quanto ao vazio usando Bash [ -z "$msha" ]
Falha (retornando 1) se vazio ou passar (retornar 0) se não estiver vazio.
Uma maneira de testar uma confirmação de mesclagem:
$ test -z $(git rev-parse --verify $commit^2 2> /dev/null) || echo MERGE COMMIT
Quanto ao Git Revert Commits, eu concordo com @rafl que a abordagem mais realista é procurar o boilerplate de mensagem revertido na mensagem de confirmação; Se alguém mudasse, detectar -se assim estaria muito envolvido.
Maneira fácil de testar o comprometimento da mesclagem:
git show --summary HEAD | grep -q ^Merge:
Isso retornará 0 para compromissos de mesclagem, 1 para compromissos não-mergulhosos. Substitua a cabeça pelo comprometimento desejado para testar.
Exemplo de uso:
if git show --summary some-branch | grep -q ^Merge: ; then
echo "some-branch is a merge"
fi
Mais uma maneira de encontrar os pais de um compromisso:
git show -s --pretty=%p <commit>
Usar %P
para hash completo. Isso imprime quantos pais HEAD
tem:
git show -s --pretty=%p HEAD | wc -w