Abandonando alterações sem excluir do histórico


180

Há um commit que simplesmente não funcionou, então eu quero abandoná-lo sem excluí-lo da história .

Atualizei a partir de uma revisão anterior e cometi, criando assim um novo chefe.


Não tenho galhos, não quero galhos, só quero continuar com a nova cabeça exatamente como é, nada extravagante, sem fusão, sem preocupações, apenas esquecendo a anterior.

Parece que não consigo descobrir como fazer isso, e estou começando a acreditar que isso não pode ser feito. Tudo o que encontro são coisas sobre galhos ou coisas sobre fusão.


1
Está no seu repositório, por isso não foi excluído do histórico. Você criou uma nova cabeça, para poder continuar fazendo revisões sem o erro. O que está impedindo você de continuar com a nova cabeça?
Ataylor 10/09/10

O que há com sua aversão aos galhos?
Andres Jaan Tack

@ Andres Não é exatamente aversão a ramos. Eu só precisava que ele funcionasse sem um passo extra estúpido de criar um apenas para fechá-lo.
o0 '.

Qualquer pessoa que esteja lendo - observe que uma ramificação já foi criada nesse cenário; observe a explicação dada nesta resposta: stackoverflow.com/a/3692607/3195477
UuDdLrLrSs

Respostas:


181

Atualize seu repositório na cabeça com a revisão que deseja esquecer e use hg commit --close-branchpara marcar essa ramificação (anônima) como fechada. Em seguida, atualize para a cabeça do ramo que você não quer, e continuar a trabalhar.

Você ainda pode ver a ramificação fechada se usar a -copção hg heads, mas ela não será exibida por padrão e hg mergesaberá que não tentará mesclar com a cabeça fechada.

Você precisará usar hg push --forcea primeira vez que enviar essa cabeça fechada para outro repositório, pois na verdade você cria cabeças adicionais no repositório remoto ao fazer o envio. Então diga à Mercurial que está tudo bem --force. As pessoas que puxam a cabeça fechada não serão incomodadas por nenhum aviso.


3
@Niall C. isso não funcionará apenas se ele tiver marcado isso como um ramo nomeado? Estou assumindo pelo que ele está dizendo que ele fez que isso é padrão
msarchet

mas ... isso não é verdade, ainda tenho as duas cabeças listadas quando ligo hg heads... Estou usando o mercurial 1.4.3, esse é um recurso mais recente?
o0 '.

2
@msarchet: AFAIK, tentando hoje, --close-branch NÃO funciona em ramos anônimos. Deveria, mas não. Espero que isso mude em alguma versão futura do Mercurial. Ramificações anônimas são muito boas, mas devem ser da primeira classe que ramificações nomeadas.
Krazy Glew

4
@KrazyGlew: O problema é que uma ramificação "anônima" é na verdade apenas uma segunda ramificação com o mesmo nome da ramificação em que se baseava. Você não está realmente tentando fechar o ramo (nomeado): está tentando descartar as alterações que está fazendo. Em outras palavras, hg branchesainda deve mostrar o nome da filial em que você está. Em vez de tentar fechar a ramificação, mescle sua ramificação anônima novamente na ramificação original, descartando todas as alterações.
StriplingWarrior

2
No meu caso, eu tenho uma ramificação chamada padrão (isso é padrão) e outra chamada padrão / mestre (acho que devido ao fato de que o depósito remoto é realmente git). hg update default / master; hg commit --close-branch; O padrão de atualização hg funcionou para mim.
MattD

68

Sei que você não deseja trabalhar com ramificações nesse estágio, mas foi exatamente isso que você fez. Quando você voltou para uma versão anterior e comprometeu algo que funcionou, você criou uma ramificação - uma ramificação sem nome, mas uma ramificação da mesma forma.


Não há problema em continuar do jeito que você é e não se preocupar em ter várias cabeças, mas se você quiser arrumar as coisas para não escolher acidentalmente a cabeça errada uma vez, poderá matar o galho antigo.

Há uma boa seção na documentação do Mercurial que leva você a várias opções em torno de Pruning Dead Branches .

Eu acho que a melhor opção para você é marcar o ramo antigo como "fechado". Se sua cabeça antiga for a revisão "123", então:

hg update -r 123
hg commit --close-branch -m 'Closing old branch'
hg update -C default

3
Blurgh - só vi a resposta de @ Niall depois que eu entrei. Voto a favor de Niall e o meu podem definhar no pool de zero pontos. :)
Nick Pierpoint

1
Eu gosto da sua resposta melhor, exige groking menos de terminologia de merucrial (que tão perto quanto eu posso dizer parece ser escolhido para confundir os usuários git)
tacaswell

8
lol é o contrário! A terminologia do mercurial foi escolhida para parecer natural para os usuários do svn, enquanto a do git é confusa como o inferno! de qualquer maneira, upvoting esta resposta, porque inclui a última -C atualização
Tobia

2
Por que você precisa -Centrar hg update? Parece que nenhum arquivo teria sido modificado, portanto, ele deve funcionar sem ele.
máximo

1
Até onde eu sei, você não precisa de um C em lugar nenhum. no entanto, se houver alterações pendentes ao tentar atualizar, você será abortado.
Eli Albert

21

Primeiro de tudo, digite:

hg heads

Imagine, você tem três cabeças listadas:

changeset:   223:d1c3deae6297
user:        Your name  <your@email.com>
date:        Mon Jun 09 02:24:23 2014 +0200
summary:     commit description #3

changeset:   123:91c5402959z3
user:        Your name <your@email.com>
date:        Sat Dec 23 16:05:38 2013 +0200
summary:     commit description #2

changeset:   59:81b9804156a8
user:        Your name <your@email.com>
date:        Sat Sep 14 13:14:40 2013 +0200
summary:     commit description #1

Digamos que você queira manter a última cabeça ativa (223) e fechar o resto.

Você faria o seguinte:

Feche a cabeça # 59

hg up -r 59
hg ci --close-branch -m "clean up heads; approach abandoned"

Feche a cabeça # 123

hg up -r 123
hg ci --close-branch -m "clean up heads; approach abandoned"

Confirme as alterações

hg push

Não se esqueça de mudar para a cabeça certa no final

hg up -r 223

E você terminou.


Este é um bom tutorial, mas o exemplo de mensagens de confirmação é um pouco meta. Eu incluiria exemplos melhores para que aqueles que aprendam com você possam fornecer melhores mensagens de confirmação. Algo como --close-branch -m "Closing branch - technique #2 abandoned in favor of technique #3".
Jason R. Coombs

5
Além disso, você deve terminar no final, exceto que sua cópia de trabalho ainda está na cabeça que você acabou de fechar. Cometer outra mudança aconteceria na cabeça fechada, reabrindo-a. Você desejará hg up -r 223antes de fazer alterações.
Jason R. Coombs

@ Jason R. Coombs: Certo!
Artur Barseghyan

de acordo com @Niall, e minha própria experiência agora, você precisará hg push --force, não apenas hg pushpara passar pelo aviso de pressionar várias cabeças.
craq 25/05

1
@ Artur Eu concordo em geral. Nesse caso, hg pushpor si só não funcionou para mim. Como você recomenda que as alterações sejam transferidas para um repositório externo se ele se recusar devido a várias cabeças?
craq 25/05

12

Você quer usar hg backout. Isso remove as alterações feitas pelo conjunto de alterações de qualquer conjunto de alterações filho.

Confira isso para uma boa explicação. Recuperação mercurial


2
Esta é exatamente a resposta certa. O backout adiciona o inverso de um conjunto de alterações, desfazendo o trabalho e fornecendo uma mensagem de confirmação para você se lembrar por que não gostou da ideia.
Ry4an Brase 11/09/10

7
Na verdade, eu discordo - abandonar o trabalho de uma só maneira e recomeçar de um bom ponto de partida parece um padrão de trabalho mais limpo do que usar backouts. Especialmente porque você não pode fazer backup de mais de um conjunto de alterações por vez.
Martin Geisler

1
@ Martin Geisler, bem, eu concordo com isso, em geral, mas o OP afirmou que ele queria abandonar as alterações sem ramos
msarchet

2
@ Martin Geisler sim eu sou todo para ramificação só às vezes nuking uma má mudança é o melhor
msarchet

1
às vezes pode ser útil, mas não era exatamente o que eu queria. Obrigado mesmo assim :)
o0 '.

2

As respostas de Niall e Nick são diretas. Como me pego criando muitas cabeças pendentes, acabei escrevendo um pseudônimo para fechar cabeças mais facilmente. Adicionando isso ao seu .hgrc:

[alias]
behead = !REV=$($HG id -i); $HG update $@ -q && $HG ci --close-branch -m "Closing dead head" && $HG update $REV -q

(se você já tem uma [alias]seção, pode anexá-la)

Agora você pode fechar uma cabeça em um único comando (e sem precisar atualizar manualmente para um conjunto de alterações diferente) assim:

$ hg behead 123

Nota: o alias tira proveito do fato de que os aliases do Mercurial podem ser comandos de shell . Isso significa que provavelmente funcionará apenas no UNIX, não no Windows.


2

Uma alternativa para fechar ou remover o ramo indesejado seria fundi- lo de uma maneira que descarte totalmente seus efeitos, mas o deixe na história. Essa abordagem permitirá que essas alterações indesejadas se propaguem em um push - portanto, use-a apenas se esse for o efeito pretendido.

Digamos que o histórico do conjunto de alterações seja assim:

1-2-3-4-5-6    
       \    
        7-8-*

e é 5e 6que não é mais desejado.

Você consegue fazer isso:

hg up 8
hg merge -r 6 -t :local
hg commit ...

o que criará isso:

1-2-3-4-5-6    
       \   \
        7-8-9-*

A atualização 8garante que você esteja trabalhando no cabeçalho desejado no histórico, que deseja manter.

O -t :localcomando instrui o hg a usar a "ferramenta" de mesclagem chamada local, que diz para ignorar as alterações do outro ramo, ou seja, aquele NÃO representado pelo estado atual da pasta de trabalho. Mais informações .

Assim, as alterações indesejadas 5e 6são preservadas na história, mas não afetam nada mais recente.


2

Este é um caso de uso para a extensão Evolve . No momento, ele não é fornecido com o Mercurial, por isso é tecnicamente uma extensão de terceiros. Mas está sendo usado muito fortemente por várias pessoas, incluindo desenvolvedores do Mercurial, está sendo desenvolvido ativamente e não vai a lugar algum.

Com a extensão Evolve, você simplesmente

hg prune -r revname

e seguir com sua vida. O cset ainda estará lá, mas obsoleto. Ele não estará visível a menos que você passe a --hiddenopção para os comandos do Mercurial e, por padrão, não será enviado para repositórios remotos. Embora eu pense que você pode forçá-lo, se realmente quiser.

Se o cset que você está removendo tiver ancestrais que você deseja manter, será necessário executar hg evolvepara rebase desses conjuntos de alterações. hg evolvefará isso automaticamente. Caso contrário, você não precisa fazer nada.


1

Você pode clonar seu repositório corrompido para um novo sem clonar essa cabeça indesejada. Em seguida, remova o repositório antigo, mova o clone recém-criado para o local original e continue trabalhando com ele. Isso levará algum tempo, mas você obterá um repositório perfeitamente limpo sem um sinal dessa revisão indesejada.

hg clone --rev myGoodResition myDirtyRepo myCleanRepo

1
Isso não é totalmente o que eu pedi, desculpe.
o0 '.

4
@ Kristof: isso é uma piada? Releia a primeira linha do meu post: "abandone-o sem excluí-lo do histórico "
o0 '.

-1

Eu já tive esse problema várias vezes quando desejo decapitar uma cabeça que foi criada com erro. Eu sempre quero vê-lo desaparecer da face da Terra.

Na sua cópia local, obtenha as últimas e, em seguida:

  1. Encontre o início de uma cabeça que deseja despir (onde um novo pescoço começa a se ramificar), obtenha o número da revisão

  2. Tire isso.


Fonte: TipsAndTricks .

Fonte: PruningDeadBranches # Using_strip .

hg --config extensions.hgext.mq= strip -n <rev>
  1. Faça uma atualização trivial de arquivo (adicione um espaço em branco a um arquivo), confirme e empurre.

Seu repositório agora deve ter a cabeça despida. A última etapa é importante, pois a remoção não cria nenhuma alteração que você possa enviar ao seu repositório central. Sem o último passo, você só retirou a cabeça localmente.


1
Porém, empurrar nunca exclui nada do repositório remoto. Ele apenas adiciona informações. Se o conjunto de alterações já estiver no repositório central, você precisará usar a extensão evoluir ou removê-la de alguma forma no próprio servidor central. Se o conjunto de alterações ainda não estiver no repositório central, removê-lo localmente será suficiente sem necessidade de envio por push.
Ben
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.