O que o Claude Code grava nos seus commits
Veja o trailer Co-authored-by e o link claude.ai que sessões cloud adicionam aos commits. Confirme o texto real e controle-o antes do git push.
O que o Claude Code inclui num commit
O Claude Code adiciona um trailer Co-authored-by: no final das mensagens de commit que escreve e uma linha de atribuição às descrições dos pull requests que abre. As sessões executadas na cloud ou através do Remote Control também acrescentam uma ligação para a sessão em claude.ai. Todo esse conteúdo é texto simples armazenado no histórico do git. Depois de o enviar para um repositório público, ele torna-se público e permanece lá até alguém reescrever o histórico.
O texto exato mudou entre releases. Por isso, não confie numa cópia do trailer apresentada em nenhum guia, incluindo este. Leia os seus próprios commits. Os comandos git abaixo são a parte duradoura deste tópico: o tratamento de trailers do git funciona da mesma forma há anos e continuará a funcionar assim mesmo depois de a próxima release alterar o texto.
O que um trailer do git realmente é
Um trailer é uma linha com o formato Token: value no último bloco da mensagem de um commit. O Git não fornece uma lista fixa de tokens. Signed-off-by:, Reviewed-by:, Fixes: e Co-authored-by: são convenções baseadas no mesmo mecanismo, e um forge, ou seja, o site que aloja o repositório, como GitHub ou GitLab, lê essas linhas para decidir o que mostrar na página do commit.
O Git é rigoroso quanto à posição desse bloco. A documentação de git interpret-trailers indica que o grupo deve ser precedido por uma ou mais linhas vazias, deve ficar no fim da mensagem ou imediatamente antes de uma linha que comece com ---, e deve conter apenas trailers ou "conter pelo menos um trailer gerado pelo Git ou configurado pelo utilizador e ser constituído por pelo menos 25% de trailers".
Esta última regra é importante neste caso. Um URL isolado ou uma linha de texto no bloco final não é um trailer, e linhas não pertencentes a trailers em quantidade suficiente impedem que todo o bloco seja analisado como trailers. Por isso, um commit pode parecer conter uma linha Co-authored-by:, enquanto todas as ferramentas que leem trailers corretamente não encontram nada.
Como leio os trailers que já estão no meu histórico?
Comece pela mensagem bruta do commit mais recente.
git log -1 --format=%B%B mostra o assunto e o corpo exatamente como estão armazenados, sem quebra de linha nem reformatação. Essa saída é a fonte de verdade. Tudo o que um forge mostra é uma renderização dela.
Agora peça ao git para indicar quais dessas linhas ele considera trailers.
git log -1 --format=%B | git interpret-trailers --parse--parse é uma forma abreviada de --only-trailers --only-input --unfold, portanto a saída contém apenas o bloco de trailers. O resultado esperado tem uma linha por trailer. Uma saída vazia, quando é possível ver claramente uma linha Co-authored-by:, indica que o bloco não cumpriu as regras de posicionamento acima.
Para pesquisar em todo o histórico, peça o trailer pela chave.
git log --format='%h %(trailers:key=Co-authored-by,valueonly)'Versões mais antigas do git não suportam a opção key= em %(trailers). Uma pesquisa no texto da mensagem funciona em todas as versões.
git log -i --grep='^Co-authored-by:' --format='%h %an %s'--grep corresponde à mensagem do commit e -i torna a pesquisa independente de maiúsculas e minúsculas. Isso é importante porque a capitalização deste trailer não tem sido consistente entre as ferramentas. Antes de fazer push, limite a consulta ao que ainda não enviou.
git log origin/main..HEAD --format=%BEsses commits ainda estão apenas localmente, portanto ainda pode alterá-los sem grande custo.
O que Co-authored-by: faz com a atribuição no GitHub?
O GitHub lê o trailer e mostra um segundo autor na página do commit. Ele associa esse autor a um perfil somente quando o endereço de email pertence a uma conta. A documentação do próprio GitHub diz que os commits aparecem no gráfico de contribuições quando são "made with an email address that is connected to your account on GitHub", portanto um endereço que não pertence a ninguém não pode ser associado a um perfil. Para uma dupla de pessoas, esse é o objetivo: o endereço do seu colega está associado à conta dele, e o commit conta para os dois. Quando nenhuma conta possui o endereço, o trailer altera o que a página do commit exibe, mas não altera a lista de contribuidores do repositório.
O próprio Git ignora completamente o trailer. git shortlog -sn e git log --author leem o cabeçalho do autor, que contém o seu nome e o seu email, portanto nenhuma contagem local mostrará o coautor. A atribuição aqui é um recurso da forge aplicado sobre uma convenção de texto simples. Essa é a distinção entre o próprio git e a forge onde você o hospeda.
O link da sessão é um problema diferente
Um trailer identifica um coautor. Um URL de sessão é um apontador para uma transcrição. A documentação de referência das definições do Claude Code identifica attribution.sessionUrl como a chave que omite "the claude.ai session link from cloud and Remote Control commits", o que também indica a origem do link: sessões na Web e sessões conduzidas através do Remote Control.
O link não é uma credencial. A possibilidade de alguém abrir essa sessão é determinada pelo acesso à conta, não pelo facto de o URL permanecer desconhecido. O motivo para o manter fora de um repositório público é mais simples. Trata-se de texto público permanente que identifica um ID de sessão interno e aponta para uma transcrição de trabalho que nunca foi escrita para um público. Num repositório privado, aplica-se o argumento oposto, porque um revisor pode seguir o link e ler como a alteração foi obtida. O local onde essas transcrições são guardadas e o tempo durante o qual permanecem disponíveis são explicados em como o Claude Code guarda as sessões e as retoma.
As definições que controlam a atribuição de commits do Claude Code
Verificado na referência de definições do Claude Code em 1 de setembro de 2026, estas chaves estão documentadas sob o título "Git e atribuição":
attribution: "Personaliza a atribuição que o Claude Code adiciona aos commits e pull requests"attribution.commit: "Altera ou oculta o trailer que o Claude Code adiciona aos commits"attribution.pr: "Altera ou oculta a linha de atribuição nas descrições de pull requests"attribution.sessionUrl: "Omite a ligação da sessão claude.ai dos commits na cloud e do Remote Control"includeGitInstructions: "Remove as instruções incorporadas para commits e PR do system prompt"includeCoAuthoredBy: marcada como obsoleta, com a nota "useattributionpara ocultar ou alterar a atribuição de commits e PR"
Consulte o valor aceite por cada chave na respetiva entrada da referência de definições, e não num guia. Os nomes das chaves são estáveis. Os valores aceites e as predefinições podem mudar, e um ficheiro de definições com o nome da chave correto, mas com um valor incorreto, falha silenciosamente.
O local onde escreve a definição determina quem a recebe. ~/.claude/settings.json aplica-se a todos os projetos que abrir. Um .claude/settings.json submetido na raiz do repositório chega a todas as pessoas que o clonarem. .claude/settings.local.json é específico para si nesse projeto, e o Claude Code adiciona-o aos seus excludes globais do git na primeira vez que escreve o ficheiro, para que este não entre nos seus commits. A precedência segue esta ordem: definições geridas, linha de comandos, projeto local, projeto partilhado e utilizador. Por isso, o ficheiro local de um colega tem precedência sobre o ficheiro que submeteu. Trate uma definição submetida como uma predefinição, não como uma garantia.
Depois, verifique o resultado, porque acreditar numa definição não é uma prova. Deixe o Claude Code criar o próximo commit da forma habitual e leia o resultado.
git log -1 --format=%B
git log -1 --format=%B | git interpret-trailers --parseSe o trailer continuar a ser impresso, a alteração não chegou à sessão. Verifique qual ficheiro editou e confirme a ordem de precedência acima antes de concluir que a chave está avariada.
Os controles que não dependem de uma configuração
Uma configuração define o comportamento de uma ferramenta. Uma regra do repositório tem de continuar a ser aplicada quando um contribuidor usa outra ferramenta ou nenhuma ferramenta. O Git disponibiliza um local para colocar essa regra: o hook commit-msg é executado com o caminho para o ficheiro da mensagem como primeiro argumento e pode editar esse ficheiro ou rejeitar o commit diretamente.
#!/bin/sh
# .githooks/commit-msg
grep -qi '^co-authored-by: claude' "$1" || exit 0
grep -vi '^co-authored-by: claude' "$1" > "$1.new" && mv "$1.new" "$1"chmod +x .githooks/commit-msg
git config core.hooksPath .githooksO primeiro grep termina imediatamente quando não há nada a fazer, por isso um commit normal quase não tem custo. O segundo grava novamente a mensagem sem a linha correspondente. Faça a correspondência com um token exato em vez de procurar todos os trailers, porque um filtro escrito como "remove o último bloco" também removerá uma linha Signed-off-by: que o projeto exija.
.git/hooks não faz parte do repositório, por isso um hook colocado nesse diretório nunca chega às outras pessoas. core.hooksPath indica ao git um diretório que pode ser incluído no commit, e cada pessoa ainda executa essa linha git config por conta própria. O Git não o configura automaticamente. Isso é intencional: um repositório que pudesse instalar os seus próprios executáveis durante o clone permitiria executar código na sua máquina.
Para rejeitar o commit em vez de o reescrever, escreva uma mensagem no erro padrão e execute exit 1 a partir do hook. Num repositório partilhado, rejeitar é a opção correta, porque editar silenciosamente a mensagem de commit de outra pessoa oculta a regra em vez de a explicar. Esta é uma camada diferente dos hooks do próprio agente, que são executados numa chamada de ferramenta antes de o git ser envolvido, e como um hook do Claude Code corresponde a uma ferramenta e a bloqueia aborda esse lado.
Nenhuma dessas opções ajuda com um pull request de um fork, porque o hook está numa máquina que não controla. Uma verificação no CI (integração contínua) é a única camada que vê todos os commits antes de estes serem integrados.
if git log --format=%B "origin/${BASE_BRANCH:-main}..HEAD" | grep -qi '^co-authored-by: claude'; then
echo "Attribution trailer found. Rewrite the branch before merging." >&2
exit 1
fiRegiste também a regra, além de a aplicar. Um AGENTS.md colocado junto de um CONTRIBUTING.md legível por pessoas transmite a mesma informação ao agente e à pessoa, e a verificação no CI é o que garante que ela é cumprida.
Remover o trailer antes de fazer push
Para o commit que acabou de criar:
git log -1 --format=%B | grep -vi '^co-authored-by: claude' | git commit --amend -F --F - lê a nova mensagem a partir da entrada padrão. O Git remove as linhas vazias no início e no fim de uma mensagem fornecida dessa forma, por isso a linha vazia deixada pelo trailer eliminado desaparece automaticamente. Leia novamente o resultado com git log -1 --format=%B antes de prosseguir.
Para vários commits numa branch, execute um rebase interativo em relação à branch que vai integrar e marque cada mensagem que pretende alterar como reword.
git rebase -i origin/mainCada commit, desde o primeiro alterado, recebe um novo hash, porque o hash de um commit inclui a mensagem e o respetivo pai. Isto não tem custos enquanto os commits são locais, mas pode ser dispendioso depois de serem partilhados.
Removendo o trailer depois de fazer push
Num branch usado apenas por si, reescreva-o como acima e faça push por cima dele.
git push --force-with-lease--force-with-lease recusa o push se o remoto tiver avançado desde o último fetch, para não descartar silenciosamente um commit adicionado por outra pessoa. O --force simples não faz essa verificação.
Para um trailer distribuído por um histórico longo, git filter-repo reescreve todas as mensagens de uma só vez. Execute o clone a partir da sua cópia de trabalho existente, para que a URL venha do remoto que já tem configurado.
pip install git-filter-repo
git clone "$(git remote get-url origin)" ../project-rewrite
cd ../project-rewrite
git filter-repo --message-callback '
return b"\n".join(l for l in message.split(b"\n") if not l.lower().startswith(b"co-authored-by: claude"))
'O callback recebe cada mensagem como bytes e devolve a mensagem a armazenar. Por isso, cada string nele tem o prefixo b. filter-repo recusa executar num repositório que não seja um clone novo, a menos que passe --force. Ao terminar, remove o remoto origin, para impedir que faça push da reescrita por engano. Adicione o remoto novamente de forma deliberada, faça force-push e peça a todos que façam clone novamente, porque todos os hashes que têm estão agora incorretos.
Tenha claro o que uma reescrita não pode fazer. Ela altera a sua cópia do repositório. Não altera forks, clones existentes, mirrors, páginas de pull request que já tenham citado a mensagem nem um índice de pesquisa de código que tenha rastreado o repositório na semana passada. Para um segredo exposto, a correção é rodar o segredo; a reescrita serve para limpar o histórico. Um trailer de divulgação não é um segredo. Por isso, compare uma reescrita de todo o histórico com o custo envolvido: todas as pull requests abertas terão de ser reconstruídas.
O que o revisor do outro lado espera
Os mantenedores não concordam sobre isto, e essa discordância é o verdadeiro motivo para verificar antes de remover qualquer coisa. Alguns projetos querem a divulgação e pedirão que a volte a incluir, porque um revisor analisa um patch escrito por uma máquina de forma diferente. Outros proíbem-na, muitas vezes devido à questão de quem é legalmente o autor da alteração. Os projetos que usam um DCO (developer certificate of origin) exigem uma linha Signed-off-by:, que é uma declaração sobre o seu direito de submeter o código, e um filtro de mensagens descuidado remove essa linha juntamente com a atribuição.
Leia primeiro o CONTRIBUTING.md. Quando o projeto não disser nada, escolha uma regra para o repositório e registe-a, porque um trailer que aparece em metade dos commits é pior do que qualquer uma das respostas: faz uma história parecer a história de dois projetos.
Se executar o agente num servidor em vez de no seu portátil, a mesma questão reaparece um nível abaixo. Executar o Claude Code numa VPS com a sua própria conta determina a que repositórios ele pode sequer aceder, e o que um agente de programação envia para fora da máquina abrange o tráfego que nunca aparece numa mensagem de commit.
FAQ
Um trailer Co-authored-by para Claude conta nas estatísticas de contribuidores do meu repositório?
Não. O GitHub associa um commit a um perfil através de um endereço de e-mail ligado a uma conta GitHub e contabiliza as contribuições com base nisso. Um endereço que não pertence a nenhuma conta não pode ser associado, por isso o trailer altera a página do commit, mas deixa a lista de contribuidores inalterada. O próprio Git nunca lê trailers para este efeito. git shortlog -sn contabiliza o cabeçalho do autor, por isso o coautor nunca aparece nessa lista.
Como encontro todos os commits que já têm o trailer?
git log -i --grep='^Co-authored-by:' --format='%h %an %s' lista-os em todo o histórico, sem distinguir maiúsculas de minúsculas. Numa versão recente do git, git log --format='%h %(trailers:key=Co-authored-by,valueonly)' lê o valor através do próprio analisador de trailers do git, em vez de procurar texto bruto. Para ver apenas o que ainda não enviou, adicione um intervalo: git log origin/main..HEAD --format=%B.
Posso remover o trailer de commits que já enviei?
Sim, reescrevendo o histórico, mas o custo é real. Numa branch usada apenas por si, faça amend ou rebase e depois git push --force-with-lease. Numa branch partilhada, todos os commits desde o primeiro editado recebem um novo hash, por isso todos os clones e todos os pull requests abertos têm de ser reconstruídos. Uma reescrita também nunca chega a forks, mirrors ou a um clone que alguém tenha criado ontem.
A ligação da sessão claude.ai numa mensagem de commit é um risco de segurança?
Não é uma credencial, e o acesso à sessão é decidido pela conta, não pela dificuldade em adivinhar o URL. O problema é ser texto público permanente que aponta para uma transcrição escrita como notas de trabalho. A documentação de referência das definições do Claude Code identifica attribution.sessionUrl como a chave que omite essa ligação dos commits na cloud e no Remote Control, e um hook commit-msg remove-a de tudo o que a definição não abrange.
Devo desativar a atribuição?
Isso depende do repositório, não de uma preferência pessoal. Num projeto público, siga o CONTRIBUTING.md, porque um maintainer que queira essa divulgação irá pedir para a voltar a ativar. Num repositório da empresa, manter o trailer é muitas vezes útil, porque informa um revisor, mesmo um ano depois, sobre o motivo pelo qual uma alteração tem aquele aspeto. Tome uma decisão para todo o repositório e aplique-a no CI, para manter o histórico consistente.