Existe uma maneira no git de obter uma data de push para um determinado commit?

91

Estou me perguntando se existe uma maneira de visualizar uma data de push associada a cada commit no log do git. Se isso não for possível, existe uma maneira de ver todos os commits em um determinado push.

Estou escrevendo um programa que precisa manter o controle dos commits conforme eles são enviados. Como o log do git é ordenado pela data do commit, não pela data do push, não consigo ver os commits mais recentes que foram enviados. Por exemplo, se um usuário se compromete em seu repositório local 2 dias antes de enviar para o master, esse commit será colocado após 2 dias de outros commits no log do repositório master.

Justkikuchi
fonte

Respostas:

77

Levei um tempo absurdamente longo para reunir informações dispersas e finalmente encontrar a melhor resposta para essa pergunta, mas agora eu sei que a tenho. Em apenas duas linhas, sem código e sem ganchos:

# required for a bare repo
git config core.logAllRefUpdates true

git reflog --date=local master

Finalmente simples.

Aviso: você provavelmente deseja substituir os valores padrão de gc.reflogExpiree gc.reflogExpireUnreachable. Verifique os git help reflogdetalhes e para entender como e por que isso funciona.

Os dois comandos acima devem ser executados dentro do clone para o qual você envia . Se isso não for possível, uma aproximação deve ser executada em outro clone permanente :

git fetch               origin        # often and *regularly*
git reflog --date=local origin/master

Nunca exclua este clone permanente ou você perderá as datas.

Março
fonte
2
Gostaria de acrescentar que no meu caso tive que fazer git reflog --date=local origin/master(nota origin/) para ver a lista de pushes. Caso contrário, apenas commits, checkouts e pulls estavam na lista (o que é útil também). Na verdade, fui apontado para ele pela resposta de @JonathanDay .
NIA
@NIA: origin / master fornecerá apenas uma aproximação. Atualizei minha resposta após seu comentário, isso esclarece?
MarcH
37

Git é um sistema de controle de versão distribuído, então você deve definir cuidadosamente o que entende por "data de envio". Por exemplo, suponha que o usuário A envie alguns commits para o repositório do usuário B. Algum ponto depois, o usuário B envia esses mesmos commits para um terceiro repositório. Em qual data você está interessado?

Estou especulando que você tem um repositório compartilhado e deseja que os usuários desse repositório compartilhado possam determinar quando algo foi publicado no repositório. Se isso for verdade, você terá que coletar essas informações no repositório compartilhado.

As más notícias

Infelizmente, não há como acrescentar a data às mensagens de confirmação. Isso mudaria o ID de confirmação (que é um hash SHA1 do conteúdo), causando todos os tipos de problemas.

As boas notícias

Felizmente, o Git tem um recurso (relativamente novo) chamado notas . Este recurso permite que você anexe texto arbitrário aos commits, que git logpodem ser exibidos. As notas podem ser editadas e compartilhadas com outras pessoas.

Você pode usar o recurso de notas para anexar uma mensagem "este commit foi recebido em [data]" a cada commit conforme é recebido pelo repositório compartilhado.

Veja git help notespara detalhes.

Como registrar a data

Esta é a abordagem que recomendo:

  1. Modifique o post-receivegancho em seu repositório compartilhado para percorrer cada commit acessível para cada referência atualizada.
  2. Para cada commit, acrescente algo como "[usuário] de [repository_url] adicionou este commit a [ref] em [data]" na nota do commit.

    Você pode querer usar um ref de notas dedicado a este propósito (como refs/notes/received-on) em vez do padrão refs/notes/commits. Isso evitará conflitos com notas criadas para outros fins.

  3. Modifique seu receivegancho para negar atualizações em sua referência de notas (para evitar que os usuários acidentalmente ou propositadamente mexam com as notas).
  4. Diga a todos os usuários para executar os seguintes comandos de dentro de sua árvore de trabalho:

    # Fetch all notes from the shared repository.
    # Assumes the shared repository remote is named 'origin'.
    git config --add remote.origin.fetch '+refs/notes/*:refs/remote-notes/origin/*'
    
    # Show all notes from the shared repository when running 'git log'
    git config --add notes.displayRef 'refs/remote-notes/origin/*'
    

    Esta etapa é necessária porque o Git ignora referências não ramificadas e não tags nos repositórios upstream por padrão.

O acima pressupõe que as referências são apenas avançadas, nunca excluídas ou atualizadas à força. Você provavelmente vai querer que o post-receivegancho também acrescente notas "removidas em [data]" para lidar com esses casos.

Richard Hansen
fonte
Usei sua ideia em meu blog mnaoumov.wordpress.com/2013/01/31/git-get-push-date
mnaoumov
7
git reflog show origin/master --pretty='%h %gd %gs %s' --date=iso

Isso parece funcionar muito bem para mim. A data do committer (% cd) é enganosa porque não é necessariamente igual à data de envio. A opção --date = iso, entretanto , produzirá a data de envio / busca .

Observe, se você buscou da origem / master, ele imprimirá a data em que você buscou; NÃO a data em que outra pessoa enviou o commit.

 - %h:  abrev. hash
 - %gd: human readable reflog selector
 - %gs: reflog subject
 - %s:  subject/commit message

Bônus: você pode, é claro, fazer uma formatação mais bonita. Até agora, gosto deste código de cores. É um pouco demais para digitar. Isso produzirá o SHA em vermelho, o seletor de reflog em ciano e o reflog em verde.

git reflog show origin/master --pretty='format:%C(red)%h%Creset %C(cyan)%gd%Creset %C(green)%gs%Creset: %s' --date=iso
VC
fonte
Hi VC significa que se a saída do comando "reflog show origin / master --pretty = '% Cred% h% Creset -% C (amarelo)% gd% Creset% Cblue (% gs)% Creset% s' - -date = iso "is" da4c192cd -origin / master @ {2019-02-07 08:13:40 +0100} (pull: fast-forward) JIRA-2542 melhorar relatório de teste ", significa então o conteúdo do meu ramo JIRA -2542 foi mesclado na origem / mestre por meio de um fast-froward em 07/02/2019 08:13:40?
Simon
Oi Simon, sim. Você fez um git pull em seu branch e ele foi mesclado em origin / master via fast-forward naquele momento.
VC
Funciona apenas no repositório do autor. Se eu clonar um repositório, o valor ficará vazio. Você não pode ver o tempo de empurrão de outras pessoas.
ramwin
6

Dê uma olhada em git reflog show master. Provavelmente não é o formato exato que você deseja, mas deve indicar a direção certa.

Outra ideia é executar um script dentro de um push hook.

Karl Bielefeldt
fonte
Pensei em executar o push hook, mas parece que isso deve ser um último esforço. Com um gancho, parece que todo usuário teria que ter esse gancho em cada um de seus repositórios. Você pode ser mais específico sobre o git reflog show master? Eu quero ser capaz de ver a data de envio dos commits individuais de cada usuário.
justkikuchi
git reflog mostra a ordem das alterações em qualquer repositório em que você o executa. Não tenho certeza se há uma maneira direta de obter a data, mas .git/logs/refs/heads/mastermostra um carimbo de data / hora.
Karl Bielefeldt
3
Quanto ganchos, existem receber ganchos que funcionam na máquina que você empurrar para . Como o push é relevante apenas em relação a um repo específico, estou assumindo que você tem um certo repo "abençoado" no qual deseja executá-lo. O mesmo vale git reflogpara esse assunto.
Karl Bielefeldt
5

Esta resposta sobre a inspeção do reflog no remoto pode ajudar ( https://stackoverflow.com/a/8791295/336905 ), fornecendo informações sobre qual branch foi enviado por push, mesmo que não mostre quais commits foram enviados, mas você poderia fazer uma correlação cruzada encontrando o próximo push após a data de confirmação local. Não é infalível, mas útil se você ainda não implementou a excelente sugestão de notas de @RichardHansen postada anteriormente

Jonathan Day
fonte
1
Com uma nota que reflog de origin/branchmostrará apenas as mudanças feitas na máquina atual , isto é extremamente útil! Para o uso do dia-a-dia, não quero implementar nenhum gancho, então para uma pergunta simples "Hmmm, quando enviei aquele commit na semana passada?" - funciona muito bem.
NIA
4

Você também pode ver a hora de modificação do arquivo do objeto commit no diretório "objects" no repositório git no próprio servidor.

Rico
fonte
2

Por que git AuthorDate é diferente de CommitDate?

  • AuthorDate é quando o commit foi criado pela primeira vez.
  • CommitDate é quando o commit foi modificado pela última vez (por exemplo, rebase).

Você pode obtê-los com as --prettyopções de formatação:

       o    %cd: committer date
       o    %cD: committer date, RFC2822 style
       o    %cr: committer date, relative
       o    %ct: committer date, UNIX timestamp
       o    %ci: committer date, ISO 8601 format

Portanto, se você e outros desenvolvedores estão fazendo isso git rebaseantes git push, você terminará com uma data de confirmação posterior à data do autor .

Este comando mostra a data de confirmação: git log --pretty=fuller

dnozay
fonte
1

Acho que você pode usar a próxima notação para obter a data de push: git log -g --date = local

Pashh PGH
fonte