aragost Trifork: Mercurial Kick Start Exercises


Mercurial Bookmarks

There are two main ways to organize branches in Mercurial: named branches and bookmarks. Bookmarks are used for short-term feature or topic branches whereas named branches are used for long-term branches.

Ramos nomeados funcionam bem em uma configuração em que você precisa rastrear o contexto em que cada changeset foi feito; o nome do ramo fica embutido no changeset e você pode se referir a ele anos depois. Como o nome do ramo é embutido no histórico, ramos nomeados são ótimos quando se precisa auditar os registros e é necessário ver quem fez o que e quando.

Há contextos em que ramos nomeados não funcionam tão bem: se você não precisa rastrear ou quer rastrear o nome do ramo depois que o ramo já começou, então os ramos nomeados não são para você. Talvez você só queira experimentar um pouco sem se comprometer com um nome de ramo, ou talvez você queira poder mudar o nome do ramo depois.

Se é o seu caso, então os bookmarks do Mercurial serão de grande ajuda.

Note

Você deve usar a versão 2.1 ou mais recente do Mercurial para acompanhar os exemplos desta seção.

Contents

Introdução

A seguir, vamos explorar os bookmarks em detalhes, mas em resumo, um bookmark permite que você associe um nome a um changeset. Isto é útil quando se está trabalhando em várias coisas diferentes ao mesmo tempo — tal como em dois ramos de funcionalidades.

Rótulos (tags) também adicionam novos nomes a changesets, mas diferente de rótulos, bookmarks são mutáveis e transientes: você pode mover, renomear ou deletá-los e eles não são armazendos no histórico. Isto significa que bookmarks não deixam registros para auditoria.

Conceitos Básico de Bookmarks

Imagine que Alice, Bob e Carla estão escrevendo um livro de sentenças (de viagem) juntos. No projeto, eles trabalharão em sentenças de diferentes categorias, e algumas vezes terão de trabalhar em diferentes categorias ao mesmo tempo Sendo assim, eles naturalmente terão vários ramos em andamento ao mesmo tempo. Bookmarks permitirão rastrear esses ramos de modo leve.

Carla é a chefe, então ela começa criando o repositório que será usado pelo projeto:

carla$ hg init phrases
carla$ cd phrases
carla$ echo "The Phrase Book Project" > README.txt
carla$ hg add
adding README.txt
carla$ hg commit -m "Added a README" 

Alice e Bob cada um tem seu próprio clone e empurram/puxam para e a partir do repositório de Carla, que age como um repositório central. Geralmente, o repositório central fica hospedado em um servidor da empresa e os clones nas máquinas dos desenvolvedores. Mas por simplicidade, vamos manter todos os três repositórios no mesmo sistema de arquivos.

Alice e Bob agora podem fazer um clone do repositório que Carla acabou de montar. Para Alice, a clonagem será assim:

alice$ hg clone ../carla/phrases
destination directory: phrases
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
alice$ cd phrases

Elas estarão trabalhando em sentenças de diferentes categorias e começarão pela coleta de sentenças em Inglês. Carla pede a Alice para adicionar sentenças usadas para saudações:

alice$ echo "Hello!" > greetings.txt
alice$ hg add
adding greetings.txt
alice$ hg commit -m "First greeting" 

Adicionando um Bookmark

Carla pede para Alice começar a procurar por sentenças de viagem. Alice já estava trabalhando nas saudações, e gostaria de separar as duas tarefas — misturar mudanças relacionadas a saudações com mudanças de viagem tornará mais difícil a revisão depois. Portanto, Alice retornará (hg update) à revisão 0 e iniciará um novo ramo de tarefa a partir de lá. Mas para lembrar onde ela estava antes ela criará um bookmark antes. Nesse momento, o repositório dela ainda está assim:

alice-pre-bookmark.png

As mudanças relacionadas com saudações estão identificadas como estando no ramo default e sendo o changeset tip. Estes identificadores se moverão quando ela começar a trabalhar no novo ramo, então ela precisa de algo mais estável — um bookmark. Ela cria o bookmark:

alice$ hg bookmark greetings

O changeset agora tem um bookmark associado a ele:

alice-greetings-bookmark.png

Ela pode ver o bookmark usando hg bookmarks:

alice$ hg bookmarks
 * greetings                 1:0b89bcda3dcf

O asterisco (*) indica que o bookmark está ativo, o que significa que ele se moverá à medida que ela fizer novas consolidações. Como o bookmark se move a cada consolidação, ele sempre apontará para a ponta (head) do ramo em que você estiver trabalhando.

Alice deseja criar um novo ramo para sentenças de viagem. O ramo deve começar na revisão 0, de modo que ela atualiza sua revisão antes. Isto faz com que o bookmark greetings ficar inativo pois ela se moveu para fora do ramo de desenvolvimento:

alice$ hg update 0
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
alice$ hg bookmarks
   greetings                 1:0b89bcda3dcf

O bookmark permanece no lugar original:

alice-inactive-greetings.png

Isto significa que Alice podem sempre executar hg update greetings para voltar a ele novamente. Por enquanto, ela será esperta o suficiente para criar um novo bookmark chamado traveling para o novo ramo que Carla pediu para ela fazer. O novo bookmark se torna ativo automaticamente:

alice$ hg bookmark traveling
alice$ hg bookmarks
   greetings                 1:0b89bcda3dcf
 * traveling                 0:4326a390b9b6

O bookmark ativo também pode ser visto no TortoiseHg:

alice-active-traveling.png

Agora, quando Alice criar uma nova consolidação, o bookmark traveling irá, bem…, viajar com a consolidação:

alice$ echo "When does the bus arrive?" > traveling.txt
alice$ hg add traveling.txt
alice$ hg commit -m "Started on traveling phrases" 
created new head
alice-traveling-moved.png

Atualizando para um Bookmark

Agora que Alice tem bookmarks na revisão 1 e 2, ela pode usar os nomes dos bookmarks em todos os comandos que esperam um número de revisão. Isto é, ela pode usar 1 (o número de revisão local), 0b89bcda3dcf (o identificado global do changeset) e greetings (o bookmark) alternadamente:

alice$ hg log -r 1
changeset:   1:0b89bcda3dcf
bookmark:    greetings
user:        Alice <alice@example.net>
date:        Tue May 01 10:20:35 2012 +0000
summary:     First greeting
alice$ hg log -r 0b89bcda3dcf
changeset:   1:0b89bcda3dcf
bookmark:    greetings
user:        Alice <alice@example.net>
date:        Tue May 01 10:20:35 2012 +0000
summary:     First greeting
alice$ hg log -r greetings
changeset:   1:0b89bcda3dcf
bookmark:    greetings
user:        Alice <alice@example.net>
date:        Tue May 01 10:20:35 2012 +0000
summary:     First greeting

Da mesma forma que rótulos e nomes de ramos, bookmarks também funcionarão com todos os comandos — hg diff, hg merge etc.. A atualização fica assim:

alice$ hg update greetings
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
alice$ hg bookmarks
 * greetings                 1:0b89bcda3dcf
   traveling                 2:f1cd0e213eec
alice$ hg update traveling
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
alice$ hg bookmarks
   greetings                 1:0b89bcda3dcf
 * traveling                 2:f1cd0e213eec

Note como o bookmark que ela atualizou se tornou o bookmark ativo no momento. Uma nova consolidação avançará o bookmark ativo, de forma que hg update traveling é suficiente para preparar a cópia de trabalho de Alice para trabalhar no ramo traveling.

Renomeando e Removendo um Bookmark

The distinguishing feature of bookmarks compared to named branches is that they exist outside of the history. Here, “history” means the immutable changesets that cannot be changed without changing their changeset IDs. Bookmarks are not stored in the changesets and they are not part of the computation of changeset IDs. They can therefore be deleted and renamed at will.

Imagine que Alice adicione um novo bookmark:

alice$ hg bookmark some-name
alice$ hg bookmarks
   greetings                 1:0b89bcda3dcf
 * some-name                 2:f1cd0e213eec
   traveling                 2:f1cd0e213eec

Ela pode renomear o bookmark:

alice$ hg bookmark --rename some-name new-name
alice$ hg bookmarks
   greetings                 1:0b89bcda3dcf
 * new-name                  2:f1cd0e213eec
   traveling                 2:f1cd0e213eec

E também removê-lo:

alice$ hg bookmark --delete new-name
alice$ hg bookmarks
   greetings                 1:0b89bcda3dcf
   traveling                 2:f1cd0e213eec

Não fica rastro de um bookmark removido; ninguém pode dizer que um dia existiram. Isto faz com que bookmarks sejam bons para rastrear pequenos ramos de funcionalidades que não precisam ser registrados no histórico de longo prazo da mesma forma que os ramos nomeados são registrados.

Depois de remover o bookmark new-name, não há nenhum bookmark ativo. Nós continuaremos trabalhando no ramo traveling, que precisa ser ativado novamente:

alice$ hg update traveling
0 files updated, 0 files merged, 0 files removed, 0 files unresolved

Empurrando (Pushing) um Ramo de Tarefa

Enquanto Alice estava trabalhando, Carla também esteve ocupada. Ela atualizou o arquivo README com os autores:

carla$ echo "by Alice, Bob, and Carla" >> README.txt
carla$ hg commit -m "Added authors" 

Isto significa que o ramo traveling de Alice se tornará uma segunda head quando ela empurrar seus changesets. Por padrão, o Mercurial não permite que esta situação aconteça:

alice$ hg push -r traveling
pushing to /home/carla/phrases
searching for changes
abort: push creates new remote head f1cd0e213eec!
(you should pull and merge or use push -f to force)

Para investigar a situação, Alice terá de primeiro puxar e olhar o repositório pelo TortoiseHg:

alice$ hg pull
pulling from /home/carla/phrases
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads .' to see heads, 'hg merge' to merge)
alice-two-heads.png

Há três heads! Empurrar a head do ramo traveling na verdade criará duas heads no repositório remoto e o Mercurial se protege contra isso pois várias heads sem nome podem ser confusas: usuários que clonem o repositório não saberão qual head eles devem usar como a base para seu próprio trabalho. Quando só há uma head, não há dúvida — você apenas clona e começa a trabalhar.

Acima, o Mercurial sugere a mesclagem das heads ou o uso de -f para forçar o envio. Forçar costuma ser um sinal de que você não está usando a ferramenta como projetada, mas esta é uma situação que você realmente quer adicionar a opção -f. A razão é que o trabalho de Alice no ramo traveling ainda não está terminado e, por isso, ela ainda não quer misturar as mudanças desse ramo com as mudanças do ramo prncipal. Se houvesse uma correção importante no ramo principal, então ela poderia ter mesclado no seu ramo, mas aqui não é o caso.

Alice forçará o envio do seu ramo para o repositório remoto:

alice$ hg push -f -r traveling
pushing to /home/carla/phrases
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)

É muito importante que Alice restrinja a operação para empurrar apenas o ramo que ela deseja! Ela tem dois ramos que não existem no repositório de Carla, e a opção -f diz ao Mercurial para empurrar cegamente todas os changesets possíveis. Algum cuidado é necessário para empurrar um de todos os ramos privados. Aqui, a mensagem +1 heads indica que Alice fez o desejado — ela enviou um único novo ramo ao repositório.

Como as coisas se parecem a partir da perspectiva de Carla? Ela agora tem duas heads anônimas no seu repositório:

carla$ hg heads
changeset:   2:f1cd0e213eec
tag:         tip
parent:      0:4326a390b9b6
user:        Alice <alice@example.net>
date:        Tue May 01 10:20:40 2012 +0000
summary:     Started on traveling phrases

changeset:   1:4b18431b805d
user:        Carla <carla@example.net>
date:        Tue May 01 10:20:45 2012 +0000
summary:     Added authors

Chamamos de anônimo porque não há nomes associadas a elas — elas estão no mesmo ramo nomeado e não têm bookmarks:

carla$ hg bookmarks
no bookmarks set

Uma vez que Alice pretende continuar trabalhando no ramo, seria conveniente que seu bookmark fosse enviado também. Originalmente, (antes da versão 1.6 do Mercurial), bookmarks eram estritamente locais, mas agora é possível puxar e empurrar bookmarks.

Compartilhando Bookmarks

Bookmarks podem ser empurrados e puxados entre repositórios. Isto funciona sobre qualquer um dos protocolos usados pelo Mercurial: SSH, HTTP e acesso ao sistema de arquivos local. A habilidade de empurrar um bookmark é regida pelas mesmas regras de acesso a uma operação de push. Se você pode empurrar um changeset para um repositório, então você também pode empurrar um bookmark.

Bookmarks Esperados para Envio e Recebimento

Alice pode facilmente consertar seu erro anterior. Primeiro, ela usa hg outgoing -B para ver quais os bookmarks presentes no repositório local que não estão presentes no repositório do servidor (de modo análogo, hg incoming -B relatará os bookmarks presentes no servidor que não existem no repositório local):

alice$ hg outgoing -B
comparing with /home/carla/phrases
searching for changed bookmarks
   greetings                 0b89bcda3dcf
   traveling                 f1cd0e213eec

Ela tem dois bookmarks locais que não existem no servidor. Para empurrar um bookmark, basta ela usar -B ao invés de -r no comando de push:

alice$ hg push -B traveling
pushing to /home/carla/phrases
searching for changes
no changes found
exporting bookmark traveling

Isto fará o Mercurial empurrar os changesets apontados por traveling e exportar o bookmark para o servidor. Como ela já empurrou os changesets, apenas o bookmark é empurrado agora. O repositório de Carla agora está muito mais organizado que antes:

carla-with-bookmark.png

Alice publicará seu ramo gretings da mesma maneira, e fará do modo correto desta vez:

alice$ hg push -f -B greetings
pushing to /home/carla/phrases
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
exporting bookmark greetings

Trabalhando com um Bookmark Publicado

Agora que Alice publicou seu bookmark traveling, ela pode continuar trabalhando e empurrar de volta para Carla periodicamente. Isto automaticamente avançará o bookmark no servidor — a opção -B não será mais necessária:

alice$ echo "Two tickets, please!" >> traveling.txt
alice$ hg commit -m "A ticket phrase" 
alice$ hg push
pushing to /home/carla/phrases
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
updating bookmark traveling

Note a mensagem updating bookmark traveling embaixo. Isto informa a Alice que o bookmark está sincronizado nos dois repositórios.

Alice e Bob podem trabalhar juntos no mesmo ramo. Primeiro, Bob puxará o ramo de Carla. Bob precisa importar explicitamente o bookmark com a opção -B na primeira vez que puxa o ramo:

bob$ hg pull -B traveling
pulling from /home/carla/phrases
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 1 files
(run 'hg update' to get a working copy)
importing bookmark traveling
bob$ hg bookmarks
   traveling                 2:0098cff6f6d8

Note

Este comportamento mudará na versão 2.3 do Mercurial. A partir desta versão, o Mercurial automaticamente importará os bookmarks remotos dos changesets empurrados. Isto significa que Bob precisa apenas executar hg pull para pegar todos os changesets e bookmarks de Carla.

Bob irá para o ramo, fará uma mudança e a empurrará de volta:

bob$ hg update traveling
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
bob$ echo "Where is the train station?" >> traveling.txt
bob$ hg commit -m "Asking for a train station" 
bob$ hg push
pushing to /home/carla/phrases
searching for changes
note: unsynced remote changes!
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
updating bookmark traveling

Note como o bookmark traveling foi atualizado automaticamente no servidor. Geralmente, o Mercurial cuida de sincronizar um bookmark durante as operações de push e pull tão logo ele exista local e remotamente. Há uma restrição adicional: hg push apenas atualiza o bookmark remoto se ele for um ancestral do bookmark local. Se os bookmarks divergirem, então alguém mais trabalhou no ramo e duas heads deverão ser mescladas antes da publicação. Veremos isso na próxima situação.

Bookmarks Divergentes

Bob acabou de empurrar um changeset no ramo traveling, mas Alice ainda não o puxou. Antes de puxá-lo, ela faz sua própria consolidação no ramo:

alice$ echo "How much for a ticket?" >> traveling.txt
alice$ hg commit -m "Asking for the ticket price" 

Como é comum no Mercurial, ela notará a nova consolidação de Bob quando tentar empurrar de volta ao servidor:

alice$ hg push
pushing to /home/carla/phrases
searching for changes
abort: push creates new remote head e0c765eadfc4!
(you should pull and merge or use push -f to force)

Aqui ela deseja puxar e mesclar — ela não está publicando um novo ramo de funcionalidade, logo seria errado usar a opção -f.

Renomeação Automática de Bookmarks

Quando Alice puxa, ela obterá o changeset de Bob:

alice$ hg pull
pulling from /home/carla/phrases
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
divergent bookmark traveling stored as traveling@default
(run 'hg heads .' to see heads, 'hg merge' to merge)

Além da saída normal de hg pull, o Mercurial imprime uma mensagem sobre o aparecimento de um bookmark divergente que foi chamado de traveling@default. No TortoiseHg, a situação fica assim:

alice-divergent-bookmarks.png

O que aconteceu é que o Mercurial detectou que o traveling no servidor divergiu do traveling local. Como explicado acima, a divergência significa que os bookmarks são irmãos — um não é ancestral do outro. O bookmark remoto foi renomeado para traveling@default. O @default vem do caminho default. Se Alice tivesse:

[paths]
carla = /home/carla/phrases

no seu arquivo .hg/hgrc, então o bookmark teria sido renomeado para traveling@carla.

Mesclando Bookmarks Divergentes

Alice agora mesclará com a outra head. Normalmente, ela pode executar hg merge e o Mercurial automaticamente seleciona a outra head no ramo como o candidato óbvio da mesclagem. Mas isto não funciona com bookmarks:

alice$ hg merge
abort: branch 'default' has 4 heads - please merge with an explicit rev
(run 'hg heads .' to see heads)

Ela tem de especificar o bookmark divergente manualmente:

alice$ hg merge "traveling@default"
merging traveling.txt
warning: conflicts during merge.
merging traveling.txt incomplete! (edit conflicts, then use 'hg resolve --mark')
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon

Há um conflito porque Alice e Bob adicionaram uma nova linha depois da primeira linha. Alice resolve o conflito incorporando ambas as linhas no arquivo:

alice$ cat traveling.txt
When does the bus arrive?
Two tickets, please!
<<<<<<< local
How much for a ticket?
=======
Where is the train station?
>>>>>>> other
alice$ hg resolve --tool internal:local traveling.txt
alice$ echo "Where is the train station?" >> traveling.txt

Ela verifica as diferenças e como parece tudo certo, ela consolida a mesclagem:

alice$ hg diff
diff -r e0c765eadfc4 traveling.txt
--- a/traveling.txt     Tue May 01 10:21:00 2012 +0000
+++ b/traveling.txt     Tue May 01 10:21:03 2012 +0000
@@ -1,3 +1,4 @@
 When does the bus arrive?
 Two tickets, please!
 How much for a ticket?
+Where is the train station?
alice$ hg commit -m "Merged with Bob" 

Depois da mesclagem, os bookmarks divergentes ainda estão lá:

alice$ hg bookmarks
   greetings                 1:0b89bcda3dcf
 * traveling                 7:0e1a5b84f635
   traveling@default         6:888ae5a9e614

Alice não precisa mais do bookmark, então ela o apaga:

alice$ hg bookmarks --delete "traveling@default"

O repositório fica assim:

alice-merged-bookmarks.png

Note

A versão 2.3 melhorará isso: hg merge selecionará automaticamente um bookmark divergente como candidato à mesclagem. Depois que a mesclagem for consolidada, o bookmark divergente será removido automaticamente.

Quando ela empurra de volta para Carla, o bookmark traveling se moverá adiante. Antes de empurrar, ele estava apontando para 888ae5a9e614, e como 0e1a5b84f635 é um descendente, o bookmark pode se mover adiante no servidor.

alice$ hg push
pushing to /home/carla/phrases
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 1 files
updating bookmark traveling

Mesclando um Ramo de Funcionalidade

Alice e Bob coletaram três sentenças sobre viagem, e decidem que o ramo traveling pode ser mesclado de volta na linha principal.

Mesclando

Alice fará a mesclagem. Ela inicial puxando de Carla para garantir que ela tem as mudanças mais recentes. Em seguida, ela atualiza para a head sem nome onde Carla estava editando o arquivo README.txt:

alice$ hg pull
pulling from /home/carla/phrases
searching for changes
no changes found
alice$ hg update -r "head() and not bookmark()"
1 files updated, 0 files merged, 1 files removed, 0 files unresolved

In the update command, Alice used a revision set to select the changeset that is a head with no bookmark. She can see in TortoiseHg that she ended up at the correct changeset:

alice-before-merge.png

Ela pode agora simplesmente mesclar com o ramo traveling:

alice$ hg merge traveling
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
alice$ hg commit -m "Merged with traveling branch" 

O resultado é o esperado:

alice-after-merge.png

Removendo o Bookmark

o ramo foi mesclado e o bookmark não é mais necessário. Alice pode apagá-lo:

alice$ hg bookmark --delete traveling

Ela também pode empurrar a mesclagem de volta:

alice$ hg push
pushing to /home/carla/phrases
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 0 changes to 0 files (-1 heads)

Embora ela tenha removido o bookmark localmente e empurrado o changeset da mesclagem, o bookmark ainda existe no servidor:

alice$ hg incoming -B
comparing with /home/carla/phrases
searching for changed bookmarks
   traveling                 0e1a5b84f635

Para remover no servidor, Alice executa

alice$ hg push -B traveling
pushing to /home/carla/phrases
searching for changes
no changes found
deleting remote bookmark traveling

Especificar um bookmark que não existe localmente mas existe no servidor removerá o bookmark do servidor. Isto é parecido com quando ele publicou o bookmark da primeira vez: hg push -B NOME fará NOME apontar no servidor para a mesma coisa que ele aponta localmente — se NOME não existe localmente, ele também não existirá no servidor.

Alice poderia ter empurrado a mesclagem e removido o bookmark em uma única operação. Vamos ilustrar isto pela mesclagem do ramo greetings:

alice$ hg merge greetings
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
alice$ hg commit -m "Merged greetings branch" 
alice$ hg bookmark --delete greetings
alice$ hg push -B greetings -r .
pushing to /home/carla/phrases
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 0 changes to 0 files (-1 heads)
deleting remote bookmark greetings

Aqui, -B greetings é o que faz o Mercurial remover o bookmark remoto, e -r . é o que faz ele enviar o changeset da mesclagem recém criada: a revisão . (ponto) é um atalho para a revisão-pai da cópia de trabalho. Sem a opção -r ., hg push teria empurrado apenas o changeset de greetings — e assim o changeset da mesclagem não teria sido incluído na operação.

Resumo

Bookmarks fornecem uma maneira leve para rastrear várias linhas de desenvolvimento (heads) no seu repositório. As principais características dos bookmarks são:

Os principais comandos usados para trabalhar com bookmarks são:

Exercícios

  1. Uma pessoa do grupo deve criar um repositório e as outras devem cloná-lo.

  2. Crie um bookmark depois que você fez algumas consolidações.

  3. Publique seu bookmark no repositório central e puxe os outros ramos para o seu próprio repositório.

  4. See the revision set documentation and try a query like hg log -r "ancestors(NAME) - ancestors(.)" to see changesets on the branch NAME that have not yet been merged into your current revision. Revision sets also work in TortoiseHg.

  5. Atualize para um dos outros ramos e faça uma consolidação. Empurre de volta para o servidor e experimente lidar com bookmarks divergentes.

  6. Enable the rebase extension and try rebasing a feature branch on top of the main line of development. The bookmarks should follow along automatically.

História

As primeiras versões do Mercurial não tinha nem ramos nomeados nem bookmarks. Ramos nomeados foram introduzidos na versão 0.9.2 (Dezembro de 2006) e bookmarks dois anos depois. Com o passar dos anos, bookmarks ganharam funcionalidades e se tornaram mais estáveis. Eventos de destaque até a versão 2.2 do Mercurial foram:

Mercurial 1.1 (Dezembro 2008)
Bookmarks são introduzidos como uma extensão padrão.
Mercurial 1.6 (Junho de 2010)
Bookmarks podem ser empurrados. Antes, eram apenas rótulos locais para consolidações. A partir desta versão, bookmarks podem ser compartilhados ao serem publicados em um servidor remoto para que outros possam puxá-los.
Mercurial 1.8 (Março de 2011)
Os bookmarks foram promovidos e passaram a fazer parte do núcleo do Mercurial.
Mercurial 2.1 (Fevereiro de 2012)
Bookmarks divergentes são renomeados e puxados para o repositório local. Isto permite distinguir entre foo (seu bookmark) e foo@alice (bookmark da Alice).

Devido ao longo histórico das funcionalidades trazida pelos bookmarks, há alguns guias por aí que contém informação desatualizada. Você pode comparar a data da publicação do guia com a tabela acima para ver quais características que o guia provavelmente não sabe.