Eu tenho um par de commits que deveria ser apenas um. Se eu estivesse usando o git, usaria:
git rebase -i <some-commit-before>
e depois esmagá-los.
Posso fazer isso no mercurial? Se sim, como?
Eu tenho um par de commits que deveria ser apenas um. Se eu estivesse usando o git, usaria:
git rebase -i <some-commit-before>
e depois esmagá-los.
Posso fazer isso no mercurial? Se sim, como?
Respostas:
Sim, você pode fazer isso usando o mercurial sem quaisquer extensões por Concatenating Changesets .
Como alternativa, se quiser usar uma extensão, você pode usar:
Meu favorito é o hg strip --keep
comando. E então eu confirmo todas as mudanças em um commit.
É a forma mais rápida e confortável para mim, porque gosto de fazer muitos pequenos compromissos no meu trabalho diário;)
Nota 1: strip
precisa de uma extensão embutida mq
para ser habilitada.
Nota 2: Meu cliente Git / Mercurial favorito (SmartGit / Hg) anexa por --keep
parâmetro padrão durante strip
. E o que é ainda mais conveniente: oferece uma opção chamada join commits
:]
hg strip --keep --rev [rev]
Onde rev
está o número de revisão do primeiro commit que você deseja esmagar com o último
--rev
é opcional, o comando completo éhg strip --keep [rev]
hg help strip
fornece hg strip [-k] [-f] [-n] [-B bookmark] [-r] REV...
, e omitindo a revisão, fornece abort: empty revision set
.
hg strip
não é a melhor ideia. Não é exatamente seguro. Experimente hg histedit
, talvez até tente usar a extensão evoluir.
A extensão Rebase funcionou perfeitamente. Para esmagar 2 commits:
$ hg rebase --dest .~2 --base . --collapse
Dot é um atalho para a revisão atual.
É ainda mais fácil quando você tem alguns commits em um branch e deseja agrupá-los todos em um:
$ hg rebase --dest {destination branch (e.g. master)} --base . --collapse
Como funciona:
(de http://mercurial-scm.org/wiki/RebaseExtension#Collapsing )
Se você está lendo esta resposta, pode esquecer todas as outras opções mencionadas nesta resposta e usar o
fold
comando da extensão evolve .
evolve
é uma extensão do mercurial que nos ajuda a ter uma história mutável segura, embora ainda seja experimental. Você pode usá-lo clonando-o de sua repo e adicioná-lo em sua .hgrc assim.
[extensions]
evolve = ~/evolve/hgext/evolve.py
Supondo que você clonou o repo evoluir em seu diretório inicial. Agora você está pronto para ir. Você também pode procurar ajuda em hg help fold
.
Você diz fold
para esmagar / dobrar uma cadeia linear de commits que não está quebrada. O que o fold faz é criar um novo changeset que contém as mudanças de todos os changesets e marcar todos os commits como obsoletos. Você pode ter uma visão mais aprofundada sobre isso em docs .
Agora, suponha que você tenha o seguinte histórico.
a -> b -> c -> d -> e -> f -> g
Você quer esmagar e
, f
e g
. Você pode fazer
hg up g
hg fold -r e
O resultado será
a -> b -> c -> d -> h
onde h
está o changeset que contém as mudanças de todos os três commits e
, f
e g
.
Você também pode dobrar changesets do meio do histórico, ou seja, não necessariamente você precisa escolher uma corrente que inclua a ponta. Suponha que você queira desistir b
, c
e d
. Você pode fazer
hg up d
hg fold -r b
hg evolve --all
Isso resultará em
a -> i -> j
onde i
é dobrado a revisão de b
, c
, d
e j
é o mesmo conjunto de alterações como h
.
Evolve guia do usuário é uma leitura obrigatória.
--keep
opção de rebase cobre isso (seguido por marcar as revisões como secretas ou usar tira nelas depois de verificar o resultado). Até mesmo mover revisões entre outras revisões é possível com uma sequência de dois comandos de rebase.
Com o Mercurial 4.8 (novembro de 2018, 9 anos depois), você pode considerar o novo comando hg absorb
(antes era um recurso experimental ).
Consulte " Absorvendo Mudanças Comprometidas no Mercurial 4.8 "
A extensão absorb pegará cada mudança em seu diretório de trabalho, descobrirá quais commits em sua série modificaram aquela linha, e automaticamente corrigirá a mudança para aquele commit.
Se houver alguma ambigüidade (ou seja, vários commits modificados na mesma linha), então absorb irá simplesmente ignorar essa mudança e deixá-la em seu diretório de trabalho para ser resolvida manualmente.Em um nível técnico,
hg absorb
encontra todas as alterações não confirmadas e tenta mapear cada linha alterada para um commit anterior não ambíguo.
Para cada mudança que pode ser mapeada de forma limpa, as mudanças não confirmadas são absorvidas no commit anterior apropriado. As confirmações impactadas pela operação são realocadas automaticamente.
Se uma mudança não pode ser mapeada para um commit anterior inequívoco, ela é deixada sem commit e os usuários podem recorrer a um fluxo de trabalho existente (por exemplo, usandohg histedit
).A lógica de reescrita automática de
hg absorb
é implementada seguindo o histórico de linhas: Isso é fundamentalmente diferente da abordagem adotada porhg histedit
ougit rebase
, que tende a depender de estratégias de mesclagem com base na mesclagem de três vias para derivar uma nova versão de um arquivo com entrada múltipla versões.Essa abordagem combinada com o fato de que o hg absorb ignora as alterações com um commit ambíguo do aplicativo significa que o hg absorb nunca encontrará conflitos de mesclagem!
Agora, você pode estar pensando que, se ignorar as linhas com destinos de aplicativo ambíguos, o patch sempre será aplicado de forma limpa usando uma combinação clássica de 3 vias. Esta afirmação parece logicamente correta. Mas não é:
hg absorb
pode evitar conflitos de mesclagem quando a mesclagem executada porhg histedit
ougit rebase -i
falhar.
Eu acho que chistedit
(construído desde o Mercurial 2.3) é o mais próximo rebase -i
que é puro Mercurial ( chistedit
é a versão interativa do histedit
). Uma vez no histedit, o fold
comando mapeia para rebase squash
e roll
mapeia de comando para rebase fixup
. Veja histedit docs para mais informações.
Aqui está um exemplo simples. Suponha que você tenha o seguinte e deseja mover todas as alterações de 1e21c4b1 para a revisão anterior e apenas manter a mensagem da revisão anterior.
@ 1e21c4b1 drees tip
| A commit you want to squash
o b4a738a4 drees
| A commit
o 788aa028 drees
| Older stuff
Você pode executar hg chistedit -r b4a738a4
para editar o histórico de volta para b4a738a4. Em chistedit, você então move o cursor para baixo para 1e21c4b1 e pressiona r
para indicar que deseja rolar essa revisão. Observe que a ordem em histedit (do mais antigo para o mais recente) é revertida de hg log
(do mais recente para o mais antigo).
#0 pick 160:b4a738a49916 A commit
#1 ^roll 161:1e21c4b1500c
Depois de escolher suas alterações, você escolhe c
confirmá-las. O resultado é o seguinte:
@ bfa4a3be drees tip | Um compromisso de 788aa028 drees | Coisas mais antigas
Se você for relativamente novo para eles, então histedit
pode ser uma escolha melhor do que chistedit
porque fornece as descrições dos comandos no arquivo histedit para referência. Só é preciso um pouco mais de edição para definir os comandos usando a edição de texto normal (como o rebase normal).
Observe, para usar histedit
ouchistedit
você precisa adicionar histedit
às suas extensões em ~ / .hgrc:
[extensions]
histedit =
Eu sugeri chistedit
uma vez que é o mais próximo derebase -i
e funciona em qualquer lugar da história. Se você realmente quiser apenas incluir / ajustar a revisão atual na anterior, então @G. A strip
sugestão de Demecki pode ser boa, pois o que está acontecendo é claro. Está integrado desde o Mercuria 2.8. Para obter os resultados equivalentes aos acima, você pode fazer o seguinte:
hg strip .
hg add
hg commit --amend
Observe strip
, como o histedit, precisa ser habilitado em seu ~ / .hgrc:
[extensions]
strip =
Vamos supor que você queira esmagar (unir) 2 commits mais recentes.
Encontre um número de revisão
hg log -G -l 3
saída possível:
@ changeset: 156:a922d923cf6f
| branch: default
| tag: tip
| user: naXa!
| date: Thu Dec 13 15:45:58 2018 +0300
| summary: commit message 3
|
o changeset: 155:5feb73422486
| branch: default
| user: naXa!
| date: Thu Dec 13 15:22:15 2018 +0300
| summary: commit message 2
|
o changeset: 154:2e490482bd75
| branch: default
~ user: naXa!
date: Thu Dec 13 03:28:27 2018 +0300
summary: commit message 1
Ramificação de soft reset
hg strip --keep -r 155
Confirme as alterações novamente
hg commit -m "new commit message"
strip
requer que uma extensão embutida seja habilitada. Crie / edite o ~/.hgrc
arquivo de configuração com o seguinte conteúdo:
[extensions]
strip =