Eu tenho um repositório git que se parece com isso:
A -> B -> C -> D -> HEAD
Quero que o chefe do ramo aponte para A, ou seja, quero que B, C, D e HEAD desapareçam e quero que o cabeçote seja sinônimo de A.
Parece que eu posso tentar fazer uma nova reformulação (não se aplica, desde que eu coloquei alterações no meio) ou reverter. Mas como reverto várias confirmações? Eu reverto um de cada vez? A ordem é importante?
git
commit
git-revert
Conta
fonte
fonte
git push -f HEAD~4:master
(assumindo que o ramo remoto seja mestre). Sim, você pode enviar qualquer commit assim.git revert
.Respostas:
Expandindo o que escrevi em um comentário
A regra geral é que você não deve reescrever (alterar) o histórico que você publicou, porque alguém pode ter baseado seu trabalho nele. Se você reescrever (alterar) o histórico, terá problemas ao mesclar as alterações e atualizar para elas.
Portanto, a solução é criar um novo commit que reverta as alterações das quais você deseja se livrar. Você pode fazer isso usando o comando git revert .
Você tem a seguinte situação:
(as setas aqui se referem à direção do ponteiro: a referência "pai" no caso de confirmações, a confirmação superior no caso de cabeçalho de ramificação (ref de ramificação) e o nome da ramificação no caso de referência HEAD).
O que você precisa criar é o seguinte:
onde "[(BCD) ^ - 1]" significa o commit que reverte as alterações nos commits B, C, D. A matemática nos diz que (BCD) ^ - 1 = D ^ -1 C ^ -1 B ^ -1, então você pode obter a situação necessária usando os seguintes comandos:
A solução alternativa seria verificar o conteúdo da confirmação A e confirmar este estado:
Então você teria a seguinte situação:
A confirmação A 'tem o mesmo conteúdo que a confirmação A, mas é uma confirmação diferente (mensagem de confirmação, pais, data de confirmação).
A solução de Jeff Ferland, modificada por Charles Bailey, baseia-se na mesma idéia, mas usa git reset :
fonte
git checkout -f A -- .
não os excluirá, precisará fazê-lo manualmente. Eu apliquei essa estratégia agora, obrigado Jakubgit checkout foo
pode significar ramo de checkoutfoo
(alternar para branch) ou arquivo de checkout foo (do índice).--
é usado para desambiguar, por exemplo,git checkout -- foo
é sempre sobre arquivo.git revert --no-commit D C B
git revert
não aceitou vários commits; é uma adição bastante nova.Maneira limpa que eu achei útil
Este comando reverte os últimos 3 commit com apenas um commit.
Também não reescreve o histórico.
fonte
git commit
a partir daí realmente fará o commit.HEAD~3..
é o mesmo queHEAD~3..HEAD
Para fazer isso, basta usar o comando revert , especificando o intervalo de confirmações que você deseja que seja revertido.
Levando em conta o seu exemplo, você teria que fazer isso (supondo que você esteja no ramo 'master'):
Isso criará um novo commit no seu local com o commit inverso de B, C e D (o que significa que ele desfará as alterações introduzidas por esses commit):
fonte
git revert --no-commit HEAD~2..
é uma maneira um pouco mais idiomática de fazer isso. Se você estiver no ramo principal, não será necessário especificar o mestre novamente. A--no-commit
opção permite ao git tentar reverter todas as confirmações de uma só vez, em vez de encher o histórico com váriasrevert commit ...
mensagens (assumindo que é isso que você deseja).master~3
.--no-commit
(para que você obtenha um commit separado para cada reversão) e, em seguida, junte todos eles juntos em uma rebase interativa. A mensagem de confirmação combinada conterá todos os SHAs e você poderá organizá-los da maneira que desejar, usando seu editor de mensagens de confirmação favorito.Semelhante à resposta de Jakub, isso permite que você selecione facilmente confirmações consecutivas para reverter.
fonte
B^..HEAD
, caso contrário, B é excluído.git revert --no-commit B^..HEAD
ougit revert --no-commit A..HEAD
Isso funcionará como uma reversão para todos eles de uma vez. Dê uma boa mensagem de confirmação.
fonte
HEAD
se parecerA
, provavelmente deseja que o índice corresponda, portantogit reset --soft D
é provavelmente mais apropriado.git checkout A
entãogit commit
acima não funcionou para mim, mas esta resposta funcionou.git reset --mixed D
necessário? Especificamente porquereset
? É porque, sem redefinir para D, que HEAD apontaria para A, fazendo com que B, C e D fossem "pendurados" e coletados de lixo - o que não é o que ele deseja? Mas então porque--mixed
? Você já respondeu "--soft
redefinir não move o índice ..." Então, movendo o índice, isso significa que o índice conterá as alterações de D, enquanto o Working Directory conterá as alterações de A - desta maneira agit status
ougit diff
(que compara Index [D] a Diretório de Trabalho [A]) mostrará a substância; esse usuário está indo de D de volta para A?Primeiro, verifique se a sua cópia de trabalho não está modificada. Então:
e depois apenas confirmar. Não se esqueça de documentar qual é o motivo da reversão.
fonte
error: cannot apply binary patch to 'some/image.png' without full index line error: some/image.png: patch does not apply
git diff --binary HEAD commit_sha_you_want_to_revert_to | git apply
git revert A..Z
você obteriaerror: commit X is a merge but no -m option was given.
Estou tão frustrado que esta pergunta não pode ser respondida. Todas as outras questões estão relacionadas a como reverter corretamente e preservar a história. Esta pergunta diz "Eu quero que o chefe do ramo aponte para A, ou seja, quero que B, C, D e HEAD desapareçam e quero que o cabeçote seja sinônimo de A."
Eu aprendi muito lendo o post de Jakub, mas um cara da empresa (com acesso para enviar para o nosso ramo de "testes" sem solicitação de solicitação) fez 5 commits ruins, tentando consertar e consertar um erro que ele cometeu há 5 commits atrás. Não apenas isso, mas uma ou duas solicitações pull foram aceitas, que agora eram ruins. Então esqueça, eu encontrei o último bom commit (abc1234) e executei o script básico:
Eu disse aos outros 5 funcionários que trabalhavam neste repositório que é melhor anotarem suas alterações nas últimas horas e limpar / re-ramificar nos testes mais recentes. Fim da história.
fonte
git push --force-with-lease
, que reescreverá o histórico apenas se ninguém mais se comprometer com a ramificação depois ou dentro do intervalo das confirmações para vaporizar. Se outras pessoas usaram o ramo, seu histórico nunca deve ser reescrito e o commit deve ser visivelmente revertido.Esta é uma expansão de uma das soluções fornecidas na resposta de Jakub
Fui confrontado com uma situação em que as confirmações necessárias para reverter eram um pouco complexas, com várias confirmações sendo confirmadas por mesclagem e eu precisava evitar reescrever o histórico. Não pude usar uma série de
git revert
comandos porque acabei encontrando conflitos entre as alterações de reversão sendo adicionadas. Acabei seguindo os seguintes passos.Primeiro, verifique o conteúdo da confirmação do destino, deixando HEAD na ponta do ramo:
(O - garante que
<target-commit>
seja interpretado como uma confirmação em vez de um arquivo; o. Refere-se ao diretório atual.)Em seguida, determine quais arquivos foram adicionados nas confirmações sendo revertidas e, portanto, precisam ser excluídos:
Os arquivos adicionados devem aparecer com um "A" no início da linha e não deve haver outras diferenças. Agora, se algum arquivo precisar ser removido, prepare esses arquivos para remoção:
Por fim, confirme a reversão:
Se desejar, verifique se estamos de volta ao estado desejado:
Não deve haver diferenças.
fonte
git
HEAD apenas com a ponta do galho?A maneira mais fácil de reverter um grupo de confirmações no repositório compartilhado (que as pessoas usam e você deseja preservar o histórico) é usar
git revert
em conjunto com o gitrev-list
. O último fornecerá uma lista de confirmações, o primeiro fará a reversão em si.Existem duas maneiras de fazer isso. Se você deseja reverter várias confirmações em uma única confirmação, use:
isso reverterá um grupo de confirmações necessárias, mas deixe todas as alterações na sua árvore de trabalho; você deve confirmar todas elas normalmente.
Outra opção é ter uma única confirmação por alteração revertida:
Por exemplo, se você tiver uma árvore de confirmação como
para reverter as alterações de eee para bbb , execute
fonte
Nenhum deles funcionou para mim, então eu tinha três confirmações para reverter (as últimas três confirmações), então fiz:
Trabalhou como um encanto :)
fonte
Na minha opinião, uma maneira muito fácil e limpa pode ser:
volte para A
aponte a cabeça do mestre para o estado atual
Salve
fonte
git checkout master; git reset --hard A
? Ou, se não, você poderia explicar um pouco mais sobre o que isso faz?Se você quiser reverter temporariamente as confirmações de um recurso, poderá usar a série de comandos a seguir.
Aqui está como funciona
git log --pretty = on-line | grep 'feature_name' | cut -d '' -f1 | xargs -n1 git revert --no-edit
fonte