Eu estava escrevendo um script simples no computador da escola e cometendo as alterações no Git (em um repositório que estava no meu pendrive, clonado do meu computador em casa). Após várias confirmações, percebi que estava comprometendo coisas como usuário root.
Existe alguma maneira de mudar o autor desses commits para o meu nome?
git
version-control
git-filter-branch
git-rewrite-history
Flávio Amieiro
fonte
fonte
Respostas:
Alterar o autor (ou responsável) exigiria reescrever toda a história. Se você concorda com isso e acha que vale a pena, deve verificar o git filter-branch . A página do manual inclui vários exemplos para você começar. Observe também que você pode usar variáveis de ambiente para alterar o nome do autor, confirmador, datas etc. - consulte a seção "Variáveis de ambiente" da página de manual do git .
Especificamente, você pode corrigir todos os nomes e e-mails de autores errados para todos os ramos e tags com este comando (fonte: ajuda do GitHub ):
fonte
git push --force --tags origin HEAD:master
NOTA: Essa resposta altera os SHA1s, portanto, use-o em uma ramificação que já foi enviada por push. Se você deseja apenas corrigir a ortografia de um nome ou atualizar um email antigo, o git permite fazer isso sem reescrever o histórico usando
.mailmap
. Veja minha outra resposta .Usando o rebase interativo
Você poderia fazer
Em seguida, marque todos os seus commits incorretos como "editar" no arquivo rebase. Se você também deseja alterar seu primeiro commit, você deve adicioná-lo manualmente como primeira linha no arquivo rebase (siga o formato das outras linhas). Então, quando o git solicitar que você altere cada commit, faça
edite ou feche o editor que é aberto e faça
para continuar a rebase.
Você pode pular a abertura do editor aqui, acrescentando
--no-edit
para que o comando seja:Confirmação única
Como alguns comentadores observaram, se você deseja alterar apenas a confirmação mais recente, o comando rebase não é necessário. Apenas faça
Isso mudará o autor para o nome especificado, mas o commit será definido para o usuário configurado em
git config user.name
egit config user.email
. Se você deseja definir o committer para algo que você especificar, isso definirá o autor e o committer:Nota sobre Mesclar confirmações
Houve uma pequena falha na minha resposta original. Se houver algum commit de mesclagem entre o atual
HEAD
e o seu<some HEAD before all your bad commits>
, entãogit rebase
os achatará (e, a propósito, se você usar solicitações pull do GitHub, haverá uma tonelada de commits de mesclagem no seu histórico). Muitas vezes, isso pode levar a um histórico muito diferente (como alterações duplicadas podem ser "rebatizadas") e, na pior das hipóteses, podegit rebase
solicitar que você resolva conflitos difíceis de mesclagem (que provavelmente já foram resolvidos nos commits de mesclagem). A solução é usar o-p
sinalizador paragit rebase
, que preservará a estrutura de mesclagem do seu histórico. A página de manualgit rebase
alerta que o uso-p
e-i
pode levar a problemas, mas noBUGS
seção que diz "Editar confirmações e reformular suas mensagens de confirmação devem funcionar bem".Eu adicionei
-p
ao comando acima. No caso em que você está apenas alterando a confirmação mais recente, isso não é um problema.fonte
git commit --amend --reset-author
também funciona uma vezuser.name
euser.email
está configurado corretamente.<commit>
usaruser.name
euser.email
de~/.gitconfig
: executargit rebase -i <commit> --exec 'git commit --amend --reset-author --no-edit'
, salvar, sair. Não há necessidade de editar!Você também pode fazer:
Observe que, se você estiver usando este comando no prompt de comando do Windows, precisará usar em
"
vez de'
:fonte
"A previous backup already exists in refs/original/ Force overwriting the backup with -f"
desculpe, mas onde o-f
sinalizador estará quando executar este script duas vezes. Na verdade, isso está na resposta de Brian, desculpe-me pela perturbação logo após a ramificação do filtro ser a solução.Um liner, mas tenha cuidado se você tiver um repositório multiusuário - isso mudará todas as confirmações para ter o mesmo (novo) autor e confirmador.
Com quebras de linha na string (o que é possível no bash):
fonte
HEAD
no final do comando?git push --force --tags origin 'refs/heads/*'
após o comando recomendado$git push --force --tags origin 'refs/heads/master'
Isso acontece quando você não possui um $ HOME / .gitconfig inicializado. Você pode corrigir isso como:
testado com a versão 1.7.5.4 do git
fonte
--local
obras tambémgit commit --amend --reset-author --no-edit
comando é especialmente útil se você criou confirmações com as informações incorretas do autor e, em seguida, defina o autor correto apósgit config
. Salvei meu a $$ agora mesmo quando tive que atualizar meu e-mail.Para um único commit:
(extraído da resposta do asmeurer)
fonte
git help commit
,git commit --amend
altera o commit na "ponta do ramo atual" (que é HEAD). Normalmente, esse é o commit mais recente, mas você pode fazer o commit que desejar, primeiro verificando o commit comgit checkout <branch-name>
ougit checkout <commit-SHA>
.author
e não ocommitter
No caso em que apenas os poucos commits superiores possuem autores inválidos, você pode fazer isso por dentro
git rebase -i
usando oexec
comando e o--amend
commit, da seguinte maneira:que apresenta a lista editável de confirmações:
Em seguida, adicione
exec ... --author="..."
linhas após todas as linhas com autores inválidos:salve e saia do editor (para executar).
Essa solução pode demorar mais tempo do que algumas outras, mas é altamente controlável - eu sei exatamente o que confirma.
Obrigado a @asmeurer pela inspiração.
fonte
exec git commit --amend --reset-author -C HEAD
?Someone else's commit
vez demy bad commit 1
? Eu apenas tenteiHEAD^^
alterar os 2 últimos commits e funcionou perfeitamente.git rebase -i HEAD^^^^^^
você também pode escrevergit rebase -i HEAD~6
O Github tem uma boa solução , que é o seguinte script de shell:
fonte
git reset --hard HEAD^
algumas vezes nos outros repositórios locais para obtê-los para uma versão anterior,git pull
a versão alterada, e aqui estou eu sem linhas que contenhamunknown <[email protected]>
(adorei o padrão do git).git push -f
. Além disso, os repositórios locais precisam ser recolocados depois disso.Como o documento mencionou, reescrever o histórico é perigoso e quebrará os repositórios de outras pessoas.
Mas se você realmente deseja fazer isso e está em um ambiente bash (não há problema no Linux, no Windows, você pode usar o git bash, fornecido com a instalação do git), use o git filter-branch :
Para acelerar as coisas, você pode especificar uma série de revisões que deseja reescrever:
fonte
--tag-name-filter cat
é a opção "faça funcionar".--tag-name-filter cat
. Este realmente deveria ter sido o comportamento padrão.Ao assumir um commit não imerso de outro autor, existe uma maneira fácil de lidar com isso.
git commit --amend --reset-author
fonte
--no-edit
para fazer isso ainda mais fácil, como geralmente a maioria das pessoas vai querer atualizar somente o endereço de email e não a mensagem de commitVocê pode usar isso como um alias para poder:
ou para os últimos 10 confirmados:
Adicione a ~ / .gitconfig:
Fonte: https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig
Espero que seja útil.
fonte
[[ ]]
compatível com sh[ ]
(colchetes simples). Além disso, funciona muito bem, obrigado!Esta é uma versão mais elaborada da versão do @ Brian:
Para alterar o autor e o commit, você pode fazer isso (com quebras de linha na string, que é possível no bash):
Você pode receber um destes erros:
(isso significa que outra ramificação do filtro foi executada anteriormente no repositório e a referência da ramificação original foi copiada em refs / original )
Se você deseja forçar a execução apesar desses erros, adicione o
--force
sinalizador:-- --all
Pode ser necessária uma pequena explicação da opção: Faz com que a ramificação do filtro funcione em todas as revisões em todas as refs (o que inclui todas as ramificações). Isso significa, por exemplo, que as tags também são reescritas e são visíveis nas ramificações reescritas.Um "erro" comum é o de usar
HEAD
, o que significa filtrar todas as revisões apenas na ramificação atual . E, em seguida, nenhuma tag (ou outras referências) existiria na ramificação reescrita.fonte
Um único comando para alterar o autor para o último N confirma:
NOTAS
--no-edit
bandeira garante quegit commit --amend
não solicite uma confirmação extragit rebase -i
, você pode selecionar manualmente os commits onde alterar o autor,o arquivo que você editar ficará assim:
Você ainda pode modificar algumas linhas para ver onde deseja alterar o autor. Isso fornece um bom meio termo entre automação e controle: você vê as etapas que serão executadas e, depois de salvar, tudo será aplicado de uma só vez.
fonte
git rebase -i master -x ...
git rebase -i <sha1 or ref of starting point>
edit
(oue
)faça o loop dos dois comandos a seguir até processar todas as confirmações:
git commit --amend --reuse-message=HEAD --author="New Author <[email protected]>"
;git rebase --continue
Isso manterá todas as outras informações de confirmação (incluindo as datas). A
--reuse-message=HEAD
opção impede que o editor de mensagens seja iniciado.fonte
Eu uso o seguinte para reescrever o autor para um repositório inteiro, incluindo tags e todas as ramificações:
Em seguida, conforme descrito na página MAN da ramificação de filtro , remova todas as refs originais com backup
filter-branch
(isso é destrutivo, faça backup primeiro):fonte
--tag-name-filter cat
. Caso contrário, suas tags permanecerão na cadeia de confirmações original. As outras respostas não mencionam isso.Eu adaptei esta solução que funciona ingerindo um simples
author-conv-file
(o formato é o mesmo do git-cvsimport ). Ele funciona alterando todos os usuários, conforme definido emauthor-conv-file
todas as filiais.Usamos isso em conjunto com
cvs2git
para migrar nosso repositório do cvs para o git.ou seja, amostra
author-conv-file
O script:
fonte
Devo salientar que, se o único problema é que o autor / email é diferente do habitual, isso não é um problema. A correção correta é criar um arquivo chamado
.mailmap
na base do diretório com linhas comoE a partir de então, comandos como
git shortlog
considerarão esses dois nomes iguais (a menos que você diga especificamente a eles). Consulte http://schacon.github.com/git/git-shortlog.html para obter mais informações.Isso tem a vantagem de todas as outras soluções aqui, pois você não precisa reescrever o histórico, o que pode causar problemas se você tiver um upstream e é sempre uma boa maneira de perder dados acidentalmente.
É claro que, se você cometeu algo como você mesmo e deveria realmente ser outra pessoa, e não se importa em reescrever o histórico neste momento, alterar o autor do commit provavelmente é uma boa idéia para fins de atribuição (nesse caso, eu o direciono para o meu outra resposta aqui).
fonte
Eu achei as versões apresentadas muito agressivas, especialmente se você cometer patches de outros desenvolvedores, isso essencialmente roubará seu código.
A versão abaixo funciona em todas as ramificações e altera o autor e o emissor separadamente para evitar isso.
Parabéns ao leif81 pela opção all.
fonte
Altere commit
author name & email
porAmend
, substituindoold-commit with new-one
:Outra maneira
Rebasing
:fonte
A maneira mais rápida e fácil de fazer isso é usar o argumento --exec do git rebase:
Isso criará uma lista de tarefas assim:
e isso funcionará automaticamente, o que funciona quando você tem centenas de confirmações.
fonte
Se você é o único usuário deste repositório, é possível reescrever o histórico usando
git filter-branch
(como svick escreveu ) ou o script de filtrogit fast-export
/git fast-import
plus (conforme descrito no artigo mencionado na resposta do docgnome ) ou o rebase interativo . Mas qualquer um desses alteraria as revisões a partir do primeiro commit alterado; isso significa problemas para qualquer pessoa que tenha baseado suas alterações na sua pré-reescrita.RECUPERAÇÃO
Se outros desenvolvedores não basearem seu trabalho na versão pré-reescrita, a solução mais simples seria clonar novamente (clonar novamente).
Como alternativa, eles podem tentar
git rebase --pull
, o que aceleraria se não houvesse alterações em seu repositório ou refizesse sua ramificação sobre as confirmações reescritas (queremos evitar a mesclagem, pois isso manteria as reescrições pré-reescritas para sempre). Tudo isso supondo que eles não tenham comprometido o trabalho; usegit stash
para esconder as alterações caso contrário.Se outros desenvolvedores usam ramificações de recursos, e / ou
git pull --rebase
não funcionam, por exemplo, porque o upstream não está configurado, eles precisam refazer o trabalho em cima das confirmações pós-reescrita. Por exemplo, logo após buscar novas alterações (git fetch
), para ummaster
ramo baseado em / bifurcado deorigin/master
, é necessário executarAqui
origin/master@{1}
está o estado de pré-reescrita (antes da busca), consulte gitrevisions .A solução alternativa seria usar refs / replace / mecanismo, disponível no Git desde a versão 1.6.5. Nesta solução, você fornece substituições para confirmações com email errado; então qualquer um que busca 'substituir' refs (algo como
fetch = +refs/replace/*:refs/replace/*
refspec no lugar apropriado em suas.git/config
) obteria substituições transparente e aqueles que não buscar esses refs veria commits idade.O procedimento é mais ou menos assim:
Encontre todas as confirmações com email errado, por exemplo, usando
Para cada confirmação incorreta, crie uma confirmação de substituição e adicione-a ao banco de dados do objeto
Agora que você corrigiu o commit no banco de dados de objetos, é necessário dizer ao git para substituir automática e transparentemente o commit errado, corrigindo um usando o
git replace
comando:Por fim, liste todas as substituições para verificar se este procedimento foi bem-sucedido
e verifique se as substituições ocorrem
É claro que você pode automatizar esse procedimento ... bem, todos, exceto o uso
git replace
que ainda não possui o modo em lote, então você teria que usar o shell loop para isso ou substituir "manualmente".NÃO TESTADO! YMMV.
Observe que você pode encontrar alguns ângulos difíceis ao usar o
refs/replace/
mecanismo: ele é novo e ainda não está muito bem testado .fonte
Se os commits que você deseja corrigir são os mais recentes, e apenas alguns deles, você pode usar uma combinação
git reset
egit stash
voltar atrás e confirmá-los novamente depois de configurar o nome e o email corretos.A sequência será algo assim (para 2 confirmações incorretas, sem alterações pendentes):
fonte
Se você estiver usando o Eclipse com EGit, existe uma solução bastante fácil.
Suposição: você tem confirmações em uma ramificação local 'local_master_user_x' que não podem ser enviadas para uma ramificação remota 'master' devido ao usuário inválido.
fonte
Usando o rebase interativo, você pode colocar um comando de correção após cada confirmação que deseja alterar. Por exemplo:
fonte
;-)
.Note-se que as lojas git dois endereços de e-mail diferentes, um para o committer (a pessoa que cometeu a mudança) e outra para o autor (a pessoa que escreveu a mudança).
As informações do committer não são exibidas na maioria dos lugares, mas você pode vê-las com
git log -1 --format=%cn,%ce
(ou usar emshow
vez delog
especificar um commit específico).Embora alterar o autor do seu último commit seja tão simples quanto
git commit --amend --author "Author Name <[email protected]>"
, não há argumento ou argumento único para fazer o mesmo com as informações do commit .A solução é (temporariamente ou não) alterar as informações do usuário e, em seguida, alterar o commit, que atualizará o commit com as informações atuais:
fonte
path\to\repo\.git
. Ainda não tenho certeza do que você precisa fazer para eliminá-lo totalmente. Infelizmente, as alterações (?) Não parecem apagar.Hoje enfrentamos um problema em que um caractere UTF8 em um nome de autor estava causando problemas no servidor de compilação; portanto, tivemos que reescrever o histórico para corrigir isso. Os passos dados foram:
Etapa 1: altere seu nome de usuário no git para todas as confirmações futuras, conforme instruções aqui: https://help.github.com/articles/setting-your-username-in-git/
Etapa 2: execute o seguinte script bash:
Visão geral rápida: faça o check-out do seu repositório em um arquivo temporário, faça o check-out de todas as ramificações remotas, execute o script que irá reescrever o histórico, faça um push forçado do novo estado e peça a todos os seus colegas para fazer uma nova refazer para obter as alterações.
Tivemos problemas ao executar isso no OS X porque, de alguma forma, atrapalhava as terminações de linha nas mensagens de confirmação, então tivemos que executá-lo novamente em uma máquina Linux posteriormente.
fonte
Seu problema é realmente comum. Consulte " Usando o Mailmap para corrigir a lista de autores no Git "
Por uma questão de simplicidade, criei um script para facilitar o processo: git-changemail
Depois de colocar esse script em seu caminho, você pode emitir comandos como:
Alterar correspondências de autor na ramificação atual
Altere as correspondências de autor e commit em <ramificação> e <ramificação2>. Passe
-f
para a ramificação do filtro para permitir a reescrita de backupsMostrar usuários existentes no repositório
A propósito, depois de fazer suas alterações, limpe o backup da ramificação do filtro com: git-backup-clean
fonte
Experimente isso. Ele fará o mesmo que mencionado acima, mas de forma interativa.
Referência: https://github.com/majdarbash/git-author-change-script
fonte
Também quero adicionar meu exemplo. Eu quero criar uma função bash_ com determinado parâmetro.
isso funciona no mint-linux-17.3
fonte
Se você é o único usuário deste repositório ou não se preocupa em possivelmente quebrá-lo para outros usuários, sim. Se você enviou esses commits e eles existem onde outro lugar pode acessá-los, então não, a menos que você não se importe em quebrar os acordos de outras pessoas. O problema é que, alterando essas confirmações, você gerará novos SHAs que farão com que sejam tratados como confirmações diferentes. Quando alguém tenta obter esses commits alterados, a história é diferente e kaboom.
Esta página http://inputvalidation.blogspot.com/2008/08/how-to-change-git-commit-author.html descreve como fazê-lo. (Eu não tentei isso, então YMMV)
fonte
refs/replace/
mecanismo.