Estou tentando fazer uma coisa chique aqui com ganchos Git, mas realmente não sei como fazê-lo (ou se é possível).
O que eu preciso fazer é: em cada confirmação, quero pegar seu hash e atualizar um arquivo no commit com esse hash.
Alguma ideia?
Estou tentando fazer uma coisa chique aqui com ganchos Git, mas realmente não sei como fazê-lo (ou se é possível).
O que eu preciso fazer é: em cada confirmação, quero pegar seu hash e atualizar um arquivo no commit com esse hash.
Alguma ideia?
Respostas:
Eu recomendaria fazer algo semelhante ao que você tem em mente: colocar o SHA1 em um arquivo não rastreado , gerado como parte do processo de compilação / instalação / implantação. É obviamente fácil de fazer ( git rev-parse HEAD > filename
ou talvez git describe [--tags] > filename
), e evita fazer qualquer coisa maluca, como acabar com um arquivo diferente do rastreamento do git.
Seu código pode fazer referência a esse arquivo quando precisar do número da versão ou um processo de criação pode incorporar as informações no produto final. O último é, na verdade, como o próprio git obtém seus números de versão - o processo de compilação pega o número da versão do repositório e depois o cria no executável.
É impossível escrever o hash de confirmação atual: se você conseguir pré-calcular o hash de confirmação futuro - ele será alterado assim que você modificar qualquer arquivo.
No entanto, existem três opções:
pre-commit
, armazene o hash de confirmação anterior :) Você não modifica / insere confirmações em casos de 99,99%, portanto, isso funcionará. Na pior das hipóteses, você ainda pode identificar a revisão de origem.Estou trabalhando em um script de gancho, publicarei aqui 'quando terminar', mas ainda assim - antes do lançamento do Duke Nukem Forever :))
Atualização : código para .git/hooks/pre-commit
:
#!/usr/bin/env bash
set -e
#=== 'prev-commit' solution by o_O Tync
#commit_hash=$(git rev-parse --verify HEAD)
commit=$(git log -1 --pretty="%H%n%ci") # hash \n date
commit_hash=$(echo "$commit" | head -1)
commit_date=$(echo "$commit" | head -2 | tail -1) # 2010-12-28 05:16:23 +0300
branch_name=$(git symbolic-ref -q HEAD) # http://stackoverflow.com/questions/1593051/#1593487
branch_name=${branch_name##refs/heads/}
branch_name=${branch_name:-HEAD} # 'HEAD' indicates detached HEAD situation
# Write it
echo -e "prev_commit='$commit_hash'\ndate='$commit_date'\nbranch='$branch'\n" > gitcommit.py
Agora, a única coisa que precisamos é de uma ferramenta que converta prev_commit,branch
par em um hash de confirmação real :)
Não sei se essa abordagem pode diferenciar commits de fusão. Irá verificar em breve
Alguém me indicou a seção "man gitattributes" no ident, que tem o seguinte:
ident
Quando o atributo ident é definido para um caminho, o git substitui $ Id $ no objeto blob por $ Id :, seguido pelo nome do objeto do blob hexadecimal de 40 caracteres, seguido por um sinal de dólar $ no check-out. Qualquer sequência de bytes que comece com $ Id: e termina com $ no arquivo da árvore de trabalho é substituída por $ Id $ no check-in.
Se você pensar bem, é isso que o CVS, o Subversion, etc, também fazem. Se você olhar para o repositório, verá que o arquivo no repositório sempre contém, por exemplo, $ Id $. Nunca contém a expansão disso. É apenas no check-out que o texto é expandido.
ident
é o hash do próprio arquivo, não o hast do commit. De git-scm.com/book/en/… : "No entanto, esse resultado é de uso limitado. Se você usou a substituição de palavras-chave no CVS ou no Subversion, pode incluir um carimbo de data - o SHA não é tão útil, porque é bastante aleatório e você não pode dizer se um SHA é mais antigo ou mais recente que outro. " filter
dá trabalho, mas pode obter as informações de confirmação em (e fora) de um arquivo.
Isso pode ser alcançado usando o filter
atributo em gitattributes . Você precisaria fornecer um smudge
comando que insira o ID de confirmação e um clean
comando que o remova, para que o arquivo inserido não seja alterado apenas por causa do ID de confirmação.
Portanto, o ID de confirmação nunca é armazenado no blob do arquivo; acabou de ser expandido em sua cópia de trabalho. (Na verdade, inserir o ID de confirmação no blob se tornaria uma tarefa infinitamente recursiva. ☺) Qualquer pessoa que clone essa árvore precisará configurar os atributos para si mesma.
Pense fora da caixa de confirmação!
coloque isso no arquivo hooks / pós-checkout
#!/bin/sh
git describe --all --long > config/git-commit-version.txt
A versão estará disponível em qualquer lugar que você a usar.
Deixe-me explorar por que esse é um problema desafiador usando os elementos internos do git. Você pode obter o sha1 do commit atual,
#!/bin/bash
commit=$(git cat-file commit HEAD) #
sha1=($((printf "commit %s\0" $(echo "$commit" | wc -c); echo "$commit") | sha1sum))
echo ${sha1[0]}
Basicamente, você executa uma soma de verificação sha1 na mensagem retornada por git cat-file commit HEAD
. Duas coisas aparecem imediatamente como um problema quando você examina esta mensagem. Uma é a árvore sha1 e a segunda é o tempo de confirmação.
Agora, o tempo de confirmação é facilmente resolvido alterando a mensagem e adivinhando quanto tempo leva para fazer uma confirmação ou agendamento para confirmar em um horário específico. O verdadeiro problema é a árvore sha1, da qual você pode obter git ls-tree $(git write-tree) | git mktree
. Essencialmente, você está fazendo uma soma de verificação sha1 na mensagem de ls-tree, que é uma lista de todos os arquivos e sua soma de verificação sha1.
Portanto, a soma de verificação do commit sha1 depende da soma de verificação da árvore sha1, que depende diretamente dos arquivos sha1 checksum, que completam o círculo e dependem do commit sha1. Assim, você tem um problema circular com técnicas disponíveis para mim.
Com somas de verificação menos seguras , foi mostrado que é possível gravar a soma de verificação do arquivo no próprio arquivo por força bruta; no entanto, não conheço nenhum trabalho que tenha realizado essa tarefa com sha1. Isso não é impossível, mas quase impossível com nosso entendimento atual (mas quem sabe talvez daqui a alguns anos será trivial). No entanto, ainda é mais difícil usar força bruta, pois é necessário gravar a soma de verificação (confirmação) de uma soma de verificação (árvore) de uma soma de verificação (blob) no arquivo.