Pergunta

Eu tenho um repositório git que se parece com isso:

A -> B -> C -> D -> HEAD

I quer a cabeça do ramo para apontar para A, isto é que quer B, C, D, e a cabeça a desaparecer e que deseja cabeça para ser sinónimo de A.

Parece que eu pode tentar rebase (não se aplica, desde que eu tenha empurrado mudanças no meio), ou reverter. Mas como faço para reverter vários commits? Faço para reverter um de cada vez? É a ordem importante?

Foi útil?

Solução

Expandindo o que eu escrevi em um comentário

A regra geral é que você não deve reescrever a história (mudança) que você publicou, porque alguém poderia ter baseado o seu trabalho sobre ele. Se você reescrever a história (mudança), você faria problemas com fusão de suas mudanças e com a actualização para eles.

Portanto, a solução é criar um novo commit que reverte muda que você quer se livrar. Você pode fazer isso usando o git revert comando existente

.

Você tem a seguinte situação:

A <-- B  <-- C <-- D                                               <-- master <-- HEAD

(setas aqui refere-se à direção do ponteiro: a referência "pai" no caso de commits, o topo cometer no caso da cabeça de ramo (ramo ref), eo nome do ramo no caso de referência CABEÇA ).

O que você precisa criar é o seguinte:

A <-- B  <-- C <-- D <-- [(BCD)^-1]                   <-- master <-- HEAD

em que "[(BCD) ^ - 1]" significa a confirmação que reverte os alterações em submissões B, C, D. Matemática diz-nos que (BCD) ^ - 1 = D ^ -1 C ^ -1 ^ B - 1, para que possa obter a situação necessário usando os seguintes comandos:

$ git revert --no-commit D
$ git revert --no-commit C
$ git revert --no-commit B
$ git commit -m "the commit message"

solução alternativa seria a de Caixa conteúdo de cometer um, e comprometer este estado:

$ git checkout -f A -- .
$ git commit -a

Então você teria a seguinte situação:

A <-- B  <-- C <-- D <-- A'                       <-- master <-- HEAD

O cometer um' tem o mesmo conteúdo que cometem A, mas é um diferente commit (cometer mensagem, pais, data commit).

A solução por Jeff Ferland, modificado por Charles Bailey se baseia no mesma idéia, mas usos git reset :

$ git reset --hard A
$ git reset --soft @{1}  # (or ORIG_HEAD), which is D
$ git commit

Outras dicas

Para fazer isso você só tem que usar o revert comando, especificar o intervalo de commits que você quer para se reverteu.

Tendo em conta o seu exemplo, você teria que fazer isso (supondo que você está no ramo 'master'):

git revert master~3..master

Isto irá criar um novo commit no seu local com o inverso comprometer de B, C e D (o que significa que ele irá desfazer as alterações introduzidas por esses commits):

A <- B <- C <- D <- BCD' <- HEAD

Limpo maneira que eu achei útil

git revert --no-commit HEAD~3..

Isso reverterá comando últimos 3 commits com apenas um commit.

Também não reescrever a história.

Semelhante a resposta de Jakub, isto permite-lhe seleccionar facilmente commits consecutivos para reverter.

# revert all commits from B to HEAD, inclusively
$ git revert --no-commit B..HEAD  
$ git commit -m 'message'
git reset --hard a
git reset --mixed d
git commit

Isso irá funcionar como um revert para todos eles ao mesmo tempo. Dê uma boa mensagem de confirmação.

Em primeiro lugar certifique-se de que a sua cópia de trabalho não é modificado. Então:

git diff HEAD commit_sha_you_want_to_revert_to | git apply

e depois é só cometer. Não se esqueça de documentar o que é a razão para reverter.

Eu estou tão frustrado que esta questão não pode simplesmente ser respondida. Cada outra pergunta é em relação a como reverter corretamente e preservar a história. Esta questão diz "Eu quero que o chefe do ramo para apontar para um, ou seja, eu quero B, C, D, e de cabeça para desaparecer e eu quero a cabeça a ser sinônimo de A."

git checkout <branch_name>
git reset --hard <commit Hash for A>
git push -f

Eu aprendi muito lendo o post de Jakub, mas um cara na empresa (com acesso ao impulso para o nosso "testando" ramo sem Pull-Request) empurrado como 5 commits maus tentando correção e correção e corrigir um erro que cometeu 5 compromete atrás. Não só isso, mas uma ou duas solicitações Pull foram aceites, que estavam agora ruim. Então esqueça, eu encontrei a última boa commit (abc1234) e apenas executou o script básico:

git checkout testing
git reset --hard abc1234
git push -f

Eu disse aos outros 5 caras que trabalham nesta repo que melhor Anote suas mudanças para as últimas horas e Wipe / Re-Filial do último teste. Fim da história.

Esta é uma expansão de uma das soluções fornecidas em resposta de Jakub

fui confrontado com uma situação onde as modificações que eu precisava para reverter eram um tanto complexa, com vários dos commits sendo commits mesclagem, e eu precisava para evitar reescrever a história. Eu não era capaz de usar uma série de comandos git revert porque eu finalmente correu para conflitos entre a reversão mudanças que estão sendo adicionados. Acabei usando as etapas a seguir.

Em primeiro lugar, verificar o conteúdo do alvo cometer deixando CABEÇA na ponta do ramo:

$ git checkout -f <target-commit> -- .

(.. A - garante <target-commit> é interpretado como uma confirmação, em vez de um arquivo; o se refere ao diretório atual)

Em seguida, determinar quais arquivos foram adicionados nos commits sendo revertida, e, portanto, precisam ser excluídos:

$ git diff --name-status --cached <target-commit>

Os arquivos que foram adicionados deve aparecer com um "A" no início da linha, e não deve haver outras diferenças. Agora, se os arquivos precisam ser removidos, encenar esses arquivos para a remoção:

$ git rm <filespec>[ <filespec> ...]

Finalmente, comprometer a reversão:

$ git commit -m 'revert to <target-commit>'

Se desejar, ter certeza de que estamos de volta para o estado desejado:

$git diff <target-commit> <current-commit>

Não deve haver diferenças.

A maneira mais fácil de reverter um grupo de commits no repositório compartilhado (que as pessoas usam e você quer preservar a história) é usar git revert em conjunto com rev-list git. Este último irá fornecer-lhe uma lista de commits, o primeiro vai fazer o próprio revert.

Há duas maneiras de fazer isso. Se você quer os revert vários commits em um único cometer uso:

for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert -n $i; done

este irá reverter um grupo de commits que você precisa, mas deixar todas as mudanças em sua árvore de trabalho, você deve comprometer-los todos como de costume.

Outra opção é ter uma única confirmação por mudança revertidos:

for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert --no-edit -s $i; done

Por exemplo, se você tem um commit árvore como

 o---o---o---o---o---o--->    
fff eee ddd ccc bbb aaa

para reverter as alterações de eee e bbb , run

for i in `git rev-list eee^..bbb`; do git revert --no-edit -s $i; done

Nenhum desses funcionou para mim, então eu tive três commit revert (os três últimos commits), então eu fiz:

git revert HEAD
git revert HEAD~2
git revert HEAD~4
git rebase -i HEAD~3 # pick, squash, squash

Trabalhou como um encanto:)

Na minha opinião uma maneira muito fácil e limpo poderia ser:

voltar para A

git checkout -f A

cabeça de mestre ponto ao estado atual

git symbolic-ref HEAD refs/heads/master

save

git commit

Se você quiser reverter temporariamente os commits de um recurso, então você pode usar a série de comandos a seguir.

Aqui é assim que funciona

git log --pretty = oneline | grep 'feature_name' | cut -d '' -f1 | xargs -N1 git revert --no-edit

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top