Mercurial 工作流

优质
小牛编辑
128浏览
2023-12-01

使用Mercurial,您可以使用多种不同的工作流。此页面显示其中几种常用工作流及其用例。它旨在使版本跟踪的初学者能够轻松地入门并逐渐深入。它没有解释所使用的概念,因为已经有许多其他很好的这方面的资源。

还提供了向个相关的学习链接:

  • 快速入门 - 简单尝试。
  • Mercurial教程 - 更详尽的教程。
  • 理解Mercurial - Mercurial背后的概念。
  • Mercurial扩展 - 增强Mercurial功能
  • Mercurial权威指南(英文) - Mercurial的详细描述和内部原理,关于Mercurial设计的深入文章。

注意:

本指南不需要任何先前的版本控制系统知识(尽管SVN用户可能会很熟悉)。基于命令行更方便学习,因为我们将使用命令行客户端。

基本工作流

我们从简单工作流开始逐渐过渡到更复杂的工作流。由浅入深。

日志保持

用例

第一个工作流是最简单的:使用Mercurial 查看变更记录

此工作流程只需要安装Mercurial并对某些文件有写入访问权限。它是复杂工作流的基础。

工作流

准备Mercurial

作为第一步,应该先设置Mercurial中你的用户名。为此,使用文本编辑器打开文件〜/ .hgrc(或Windows主目录中的mercurial.ini),并将你的用户名添加ui部分:

[UI]
username = Mr. Johnson <johnson@smith.com>
初始化项目

现在添加一个项目:

$ hg init project
添加文件并跟踪

输入项目文件夹(例如:project),创建一些文件,然后添加并提交。

$ cd project
$ echo 'print("Hello")' > hello.py
$ hg add
$ hg commit
(默认编辑器被打开,
 输入提交消息,
 保存并关闭。)
output of hg add: adding hello.py display of hg commit (with your message): Initial commit. HG: Enter commit message. Lines beginning with 'HG:' are removed. HG: Leave message empty to abort commit. HG: -- HG: user: Mr. Johnson <johnson@smith.com> HG: branch 'default' HG: added hello.py

注意:

要避免切换到编辑器,还可以在命令行中直接输入提交消息:
$ hg commit -m "[MESSAGE]"

然后,可以使用hg log查看初始历史记录:

$ hg log
output of hg log: changeset: 0:a5ecbf5799c8 user: Mr. Johnson <johnson@smith.com> date: Sun Nov 20 11:00:00 2011 +0100 summary: Initial commit.

注意:

默认情况下,Log仅显示提交消息的第一行。要显示完整的消息,请使用
$ hg log -v

注意:

你还可以先进入项目目录,并在那里初始化版本库。
$ cd project
$ hg init

此外,你可以只添加特定文件而不是目录中的所有文件。Mercurial将只跟踪这些文件,不会知道其他文件。以下告诉mercurial跟踪名称以“file0”开头的所有文件以及file10,file11和file12。

$ hg add file0 * file10 file11 file12
保存更改

首先做一些改变:

$ echo 'print("Hello World")' > hello.py

查看哪些文件已更改,哪些文件已添加或删除,哪些文件尚未被跟踪

$ hg status
output of hg status: M hello.py

查看变更

$ hg diff
output of hg diff: diff --git a/hello.py b/hello.py --- a/hello.py +++ b/hello.py @@ -1,1 +1,1 @@ -print("Hello") +print("Hello World")

提交更改

$ hg commit

现在弹出一个编辑器,并要求输入提交消息。保存并关闭编辑器后,Mercurial会保存更改。

display of hg commit (with your message): Say Hello World, not just Hello. HG: Enter commit message. Lines beginning with 'HG:' are removed. HG: Leave message empty to abort commit. HG: -- HG: user: Mr. Johnson <johnson@smith.com> HG: branch 'default' HG: changed hello.py

历史现在看起来像这样:

output of hg log: changeset: 1:487d7a20ccbc user: Mr. Johnson <johnson@smith.com> date: Sun Nov 20 11:11:00 2011 +0100 summary: Say Hello World, not just Hello. changeset: 0:a5ecbf5799c8 user: Mr. Johnson <johnson@smith.com> date: Sun Nov 20 11:00:00 2011 +0100 summary: Initial commit.

注意:

您还可以通过hg commit -m 'MESSAGE' 直接提供提交消息。
复制和移动文件

复制或移动文件时,应告诉Mercurial进行复制或移动,以便跟踪文件之间的关系。

记得在移动或复制后提交。从基本命令中,用commit创建一个新的修订版

$ hg cp hello.py copy
$ hg mv hello.py target
$ hg diff#查看更改
$ hg commit
(输入提交消息)

现在你有两个文件,“copy”和“target”,Mercurial知道它们是如何相关的。

output of hg diff (before the commit): diff --git a/hello.py b/copy rename from hello.py rename to copy diff --git a/hello.py b/target copy from hello.py copy to target

注意:

如果您忘记进行显式复制或移动,您仍然可以通过hg addremove --similarity 100告诉Mercurial检测更改。可以使用hg help addremove了解详细信息。
查看历史记录
$ hg log

这将打印一个变更列表及其日期,提交者用户名及其提交消息。

output of hg log: changeset: 2:70eb0ca9d264 tag: tip user: Mr. Johnson <johnson@smith.com> date: Sun Nov 20 11:20:00 2011 +0100 summary: Copy and move. changeset: 1:487d7a20ccbc user: Mr. Johnson <johnson@smith.com> date: Sun Nov 20 11:11:00 2011 +0100 summary: Say Hello World, not just Hello. changeset: 0:a5ecbf5799c8 user: Mr. Johnson <johnson@smith.com> date: Sun Nov 20 11:00:00 2011 +0100 summary: Initial commit.

要查看某个修订版,可以使用-r开关(--revision)。要查看显示修订版的差异,还有-p开关( - 补丁)

$ hg log -p -r 3

独立开发者与非线性历史记录

用例

第二个工作流仍然非常简单:假设你是一个独立开发者,并且您希望使用Mercurial来跟踪更变优化您的工作流

它的工作方式与日志保持工作流类似,不同之处在于您可以回溯到之前的更改并从那里继续工作。

要开始一个新项目,需要初始化版本库,添加文件并在完成部分工作时提交。

你也可以随时检查历史记录,回顾工作过程。

工作流程

记录日志的基础知识

初始化您的项目,添加文件,查看更改并提交它们。

$ hg init project
$ cd project
$(添加文件)
$ hg add#告诉 Mercurial跟踪所有文件
$(做一些改变)
$ hg diff#查看更改
$ hg commit#提交变更
$ hg cp#复制文件或文件夹
$ hg mv#移动文件或文件夹
$ hg log#查看历史记录
查看早期的修订版

与日志保持工作流不同,您有时需要返回历史记录并直接在那里进行一些更改,例如因为早期的更改引入了一个错误,并且您希望在发生错误的地方修复它。

要查看以前版本的代码,可以使用update。我们假设要查看修订版1。

$ hg update 1

现在代码回到修订版1,第二次提交(Mercurial从0开始计数)。要检查是否有该修订版本,可以使用identify -n

$ hg identify  -n
output of hg identify -n: 1 output of ls: hello.py

注意:

不带选项的identify为你提供唯一修订ID的简短形式。该ID是Mercurial内部使用的ID。如果您告诉某人您更新的版本,您应该使用该ID,因为其他人的数字可能不同。 如果您想了解背后的原理,请阅读理解Mercurial。当你处于最新版本时,hg identify n将返回“-1”。

要更新到最新版本,可以使用“tip”作为修订名称。

$ hg update tip

注意:

如果有命令显示建议,最好的选择遵循这个建议。

注意:

hg update,你也可以使用缩写hg up。类似地,您可以将hg commit 缩写为hg ci

注意:

要获得文件的最初状态,只需通过hg update null 更新为“null” 。这是在添加任何文件之前的修订版。

注意:

如果hg identify 的输出以“+”结尾,则您的版本库具有未提交的更改。
修复早期版本中的错误

当你在某些早期版本中发现错误时,你有两个选择:可以在当前代码中修复它,或者返回历史记录并将代码准确地恢复到提交前的位置,从而创建更清晰的历史记录。

更清析的方式是,首先更新到旧版本,修复错误并提交。然后合并此修订,再提交合并。你不用担心:mercurial的合并是快速而无害的,就像你马上就会看到的那样。

我们假设该错误是在修订版1中引入的。

$ hg update 1
$ echo 'print(“Hello Mercurial”)'> hello.py
$ hg commit
output of hg commit (after entering the message): created new head

注意:

“created new head”意味着现在还有一个修订版,它没有子版本。head与项目当前状态并存。在传播之前将它们合并在一起是很好的风格。

现在修复过的文件已存储在历史记录中。我们只需要将其与当前版本的代码合并即可。

$ hg merge
output of hg merge (here): merging hello.py and copy to copy merging hello.py and target to target

如果存在冲突,请使用hg resolve - 这也是发生冲突时必须要做的事情。

首先列出有冲突的文件

$ hg resolve --list

然后一个一个地解决它们。resolve再次尝试合并

$ hg resolve conflicting_file
(必要时手工修理)

注意:

有关解决冲突的更多详细信息,请参阅Mercurial教程: 解决冲突部分。

将已修复的文件标记为已解决

$ hg resolve --mark conflicting_file

解决所有冲突后立即提交合并。即便没有冲突时,也要提交!

$ hg commit

此时,修复过的文件将与所有其他的工作合并,你可以继续编码。此外,历史记录清楚地显示了修复错误的位置,因此您始终可以检查错误的位置。

output of hg log (after the final commit): changeset: 4:3b06bba7c1a9 tag: tip parent: 3:7ff5cd572d80 parent: 2:70eb0ca9d264 user: Mr. Johnson <johnson@smith.com> date: Sun Nov 20 20:11:00 2011 +0100 summary: merge greeting and copy+move. changeset: 3:7ff5cd572d80 parent: 1:487d7a20ccbc user: Mr. Johnson <johnson@smith.com> date: Sun Nov 20 20:00:00 2011 +0100 summary: Greet Mercurial changeset: 2:70eb0ca9d264 user: Mr. Johnson <johnson@smith.com> date: Sun Nov 20 11:20:00 2011 +0100 summary: Copy and move. changeset: 1:487d7a20ccbc user: Mr. Johnson <johnson@smith.com> date: Sun Nov 20 11:11:00 2011 +0100 summary: Say Hello World, not just Hello. changeset: 0:a5ecbf5799c8 user: Mr. Johnson <johnson@smith.com> date: Sun Nov 20 11:00:00 2011 +0100 summary: Initial commit.

注意:

大多数合并都会成功。当合并冲突时,你只需要解决冲突(resolve)

因此,现在你可以通过提交早期的变更集,并将更改合并到当前代码中来初始化版本库,保存更改,更新以前的更改并在非线性历史记录中进行开发。

注意:

如果修复了早期版本中的错误,并且某些更高版本复制或移动了该文件,则修复将在合并时传播到目标文件。这是你应该总是使用hg cphg mv的主要原因。

分离功能

用例

有时您将并行开发多个功能。如果要避免混合不完整的代码版本,可以创建本地版本库的克隆,并在其自己的代码目录中开发每个功能。

完成功能后,将其拉回主目录并合并更改。

工作流

在不同的副本中工作

首先创建一份功能副本, 并进行一些更改

$ hg clone project feature1
$ cd feature1
$ hg update 3
$ echo'print("Hello feature1")'> hello.py
$ hg commit -m "Greet feature1"

现在检查从feature1 pull时会发生什么,就像在提交之前可以使用diff一样。用于拉动的相应命令是incoming

$ cd ../project
$ hg incoming ../feature1
output of hg incoming ../feature1: comparing with ../feature1 searching for changes changeset: 5:3eb7b39fcf57 tag: tip parent: 3:7ff5cd572d80 user: Arne Babenhauserheide <bab@draketo.de> date: Sun Nov 20 20:11:11 2011 +0100 summary: Greet feature1

注意:

如果你想看到的差异,你可以使用hg incoming --patch就像你可以用hg log --patch对资源库中的变化。

如果你想要这些更改,可以拉取到项目中

$ hg pull ../feature1

现在,项目中已经有feature1的历史记录,但工作目录中还不可见。因为它只存储在项目的“.hg”目录中。

output of hg pull: pulling from ../feature1 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)

注意:

从现在开始,我们所说的"版本库"是指项目中的.hg目录。

如果你没有对项目进行任何更改,那么当你使用feature1时,你可以更新到最新(hg update tip),如果你还需要做一些其他更改。需要先合并。

将feature1合并到项目代码中

$ hg merge

如果存在冲突,请使用hg resolve - 必须先解决冲突。之后,你必须明确的提交,来完成合并

$ hg commit
(输入提交消息,例如“merged feature1”)
output of hg log -r -1:-3 (the last 3 changesets): changeset: 6:e8a33691171a tag: tip parent: 4:3b06bba7c1a9 parent: 5:3eb7b39fcf57 user: Mr. Johnson <johnson@smith.com> date: Sun Nov 20 20:20:00 2011 +0100 summary: merged feature1 changeset: 5:3eb7b39fcf57 parent: 3:7ff5cd572d80 user: Arne Babenhauserheide <bab@draketo.de> date: Sun Nov 20 20:11:11 2011 +0100 summary: Greet feature1 changeset: 4:3b06bba7c1a9 parent: 3:7ff5cd572d80 parent: 2:70eb0ca9d264 user: Mr. Johnson <johnson@smith.com> date: Sun Nov 20 20:11:00 2011 +0100 summary: merge greeting and copy+move.

注意:

Mercurial提供了有效的方式指定修订版。请使用hg help revsets 查看详情。

你可以创建任意数量的克隆,还可以是在U盘中。你还可以使用它们在家中和工作中,或在桌面和笔记本电脑之间同步文件。

注意:

在没有冲突的情况下,也必须在合并后提交,因为合并会创建新的历史记录,并且你可能希望将特定的消息附加到合并(例如“merge feature1”)。

注意:

如果您需要空文件夹,请在这些文件夹中创建一个占位文件并添加该文件到版本库。
回滚错误

现在你可以并行开发不同的功能,但不时会有一个错误的提交隐藏起来。当然,你可以回到过去一个版本并合并排除错误,将所有错误都排除在合并版本之外。但是,如果你在执行另一次commitpull之前意识到错误,则有一种更简单的方法:rollback

回滚意味着撤消上次操作,这会给历史记录添加一些内容。

想象一下,你刚刚意识到你做了一个错误的提交 - 例如你没有在提交消息中看到拼写错误。要修复它你会使用

$ hg rollback
output of hg rollback: repository tip rolled back to revision 5 (undo commit) working directory now based on revisions 4 and 5

然后重做提交

$ hg commit -m "Merged Feature 1"
output of hg log -r -1:-2 (after rollback and commit): changeset: 6:3f549b33c7ef tag: tip parent: 4:3b06bba7c1a9 parent: 5:3eb7b39fcf57 user: Mr. Johnson <johnson@smith.com> date: Sun Nov 20 20:20:11 2011 +1100 summary: Merged Feature 1 changeset: 5:3eb7b39fcf57 parent: 3:7ff5cd572d80 user: Arne Babenhauserheide <bab@draketo.de> date: Sun Nov 20 20:11:11 2011 +0100 summary: Greet feature1

如果你可以使用shell的命令历史记录并且通过commit -m “message”添加了上一条消息,那么以下提交只意味着两次单击箭头键“up”并单击“enter”。

虽然它会更改您的历史记录,但回滚不会更改您的文件。它只会撤消您历史记录的最后一次添加。

但请注意,回滚本身无法撤消。如果你回滚然后忘记提交。您必须创建一个新的提交。

注意:

可以回滚,因为Mercurial在记录更改时使用事务,您可以使用事务记录来撤消上一个事务。这意味着如果您还没有提交任何新内容,也可以使用rollback撤消上次拉取。

分享变更

用例

现在我们更进一步:假设你不再是一个人独立开发,你希望与他人分享你的变更并包含其它人的变更

对此的基本要求是你必须能够看到其他人的变更。

Mercurial允许你通过包含一个简单的Web服务器来轻松实现,你可以从中拉取变更,就像从本地克隆中提取变更一样。

注意:

不过,还有其他一些方法可以分享变更。除了使用内置Web服务器,你也可以通过电子邮件发送或设置更改的共享资源库,到了那里推送你的变更,而不是拉动它们。我们稍后会介绍其中一个。

工作流程

使用内置的网络服务器

这是快速共享变更的最简单方法。

首先,想要分享其变更的人创建了Web服务器

$ hg serve

现在所有其他人都可以将他们的浏览器指向他在端口8000的IP地址(例如192.168.178.100)。然后他们将在那里查看他的所有历史记录,并可以决定是否要拉取他的更改。

$ firefox http://192.168.178.100:8000

如果他们决定包含更改,则只需从上面的URL中拉取

$ hg pull http://192.168.178.100:8000

此时,你可以像从本地版本库中取出一样工作。所有数据现在都在你的各个版本库中,你可以合并更改并使用它们,而无需与服务器版本库建立任何连接。

通过电子邮件发送更改

通常,你无法直接访问其他人的版本库。可能你还希望保密你的更改并更喜欢用内部电子邮件(如果你需要其他保护,你也可以加密电子邮件,例如使用GnuPG)。

在这种情况下,您可以轻松地将更改导出为补丁并通过电子邮件发送。

通过电子邮件发送它们的另一个原因可能是,当其他开发人员习惯于阅读电子邮件中的差异时,你需要手动审查更改。

通过Mercurial,通过电子邮件发送更改非常简单。您只需导出(export)变更并在电子邮件中附加(或复制粘贴)。然后你的同事可以导入(import)

首先检查要导出的变更

$ cd project
$ hg log

我们假设你要导出变更集3和4

$ hg export 3> change3.diff
$ hg export 4> change4.diff

现在将它们附加到电子邮件中,你的同事可以在两个差异上运行import以获取完整变更,包括你的用户信息。

要小心,他们首先clone他们的版本库以将integration目录作为沙箱

$ hg clone project integration
$ cd ingteration
$ hg import change3.diff
$ hg import change4.diff

OK。他们现在可以克隆你的变更并测试。如果他们接受了,他们会将变更拉取到主版本库中

$ cd ../project
$ hg pull ../integration

注意:

patchbomb扩展可以自动发送电子邮件,但这个工作流中并不是必须的。

注意:

您还可以发送捆绑包,这些捆绑包是您实际历史记录的片段。只需通过创建它们
$ hg bundle --base FIRST_REVISION_TO_BUNDLE changes.bundle
其他人可以通过简单地拉动它们来获取变更,就好像是实际的版本库一样
$ hg pull path / to / changes.bundle
使用共享版本库

当你还不是普通开发团队的成员时,通过电子邮件发送更改可能是最简单的方法,但它会产生额外的工作:你必须打包(bundle)变更,发送邮件,然后手动导入(import)捆绑包。幸运的是,有一种更简单的方法可以很好地运行:共享推送版本库。

到目前为止,我们通过电子邮件或拉取(pull)传输所有变更。现在我们使用另一种选择:推送(push)。顾名思义,这与拉取相反:您将变更推送(push)到另一个版本库。

但要使用它,我们首先需要有可以推动的目标。

为了安全,默认情况下,hg serve不允许推送。你可以设置为允许推送,但是当你居住在不同的时区时,这不是好的解决方案,因此我们将采用另一种方法:使用线上服务器或BitBucket等服务上使用共享版本库。这样做会有更高的起始成本,需要更长的时间来解释,但这是值得花费的努力。

如果要使用线上服务器,可以在那里使用服务并允许推送。 还有一些其他很好的方法可以推送到Mercurial版本库, 包括通过SSH进行简单访问

否则,您首先需要设置BitBucket帐户。只需在BitBucket注册。 注册(sign up)(并登录(login))后,将鼠标悬停在“版本库(Repository)”上。单击打开对话框底部的项目,显示“新建”。

输入名字和描述。如果你不相公开版本库,请选择“私有(Private)”

$ firefox http://bitbucket.org

现在你的版本库已创建,你将看到有关推送(push)它的说明。为此,您将使用类似于以下命令(仅使用不同的URL):

$ hg push https://bitbucket.org/ArneBab/hello/

(将URL替换为您创建的版本库的URL。如果你的用户名是“Foo”,并且您的版本库名为“bar”,则URL将为https://bitbucket.org/Foo/bar/)

Mercurial将询问你在BitBucket用户名和密码,然后推送(push)你的代码。

”小明,你的代码已经在线。“

要查看推送时会得到什么,您可以使用传出(outgoing)。它与本地版本库的工作方式与共享版本库相同,因此您可以使用本地版本库进行测试:

$ hg outgoing ../feature1
output of hg outgoing ../feature1 (our feature seperation repo): comparing with ../feature1 searching for changes changeset: 6:3f549b33c7ef tag: tip parent: 4:3b06bba7c1a9 parent: 5:3eb7b39fcf57 user: Mr. Johnson <johnson@smith.com> date: Sun Nov 20 20:20:11 2011 +1100 summary: Merged Feature 1

注意:

你也可以使用SSH推送到BitBucket

现在是时候告诉所有同事注册BitBucket了。

之后,你可以单击版本库的“管理员(Admin)”选项卡,并在“权限(Permission):编辑人员(Writers)”下的右侧添加同事的用户名。现在允许他们将代码推送(push)到版本库。

(如果您选择将版本库设为私有,则还需要将它们添加到“权限(Permission):读者(Readers)”中)

如果你们其中一个人现在想要发布变更,他只需将它们推送(push)到版本库,其他所有人都可以通过拉取(pull)来获取它们。

发布的变更

$ hg push https://bitbucket.org/ArneBab/hello/

将其他变更拉入本地版本库

$ hg pull https://bitbucket.org/ArneBab/hello/

开发人员也可以只是克隆(clone)这个版本库,就像你们其中一个人正在使用hg服务一样

$ hg clone https://bitbucket.org/ArneBab/hello/ hello

该本地版本库将自动配置到远程库的关联,因此新贡献者只需使用hg pushhg pull而无需URL。

注意:

为了使这个工作流程更具可伸缩性,你们每个人都可以拥有自己的BitBucket版本库,只需从其他版本库中拉取(pull)即可。通过这种方式,可以轻松地建立工作流,其中有的人负责集成,最后将检查的代码送(push)到共享拉版本库,其他所有人都可以从中获取。

注意:

可以通过SSH或共享目录将此工作流用于共享服务器而不是BitBucket。使用Mercurial的SSH URL的示例是ssh://user@example.com/path/to/repo。使用共享目录时,只需按下共享目录中的版本库位于本地驱动器上即可。

摘要

现在让我们退后一步,看看我们在哪里。

使用你已经知道的命令,稍微阅读一下hg help


。你几乎可以完全掌控你的源代码历史记录了。

意味着你现在可以使用更复杂的工作流。

其次它让你更专注于你的任务,而不是专注于你的工具。它可以帮助您专注于编码本身。

如果你还记得命令的含义,你可以做的简短摘要和检查。

创建一个项目

$ hg init project
$ cd项目
$(添加一些文件)
$ hg add
$ hg commit
(输入提交消息)

非线性历史记录开发

$(做一些改变)
$ hg commit
(输入提交消息)
$ hg update 0
$(做一些改变)
$ hg commit
(输入提交消息)
$ hg merge
$(可选hg解析)
$ hg commit
(输入提交消息)

使用功能副本

$ cd ..
$ hg clone project feature1
$ cd feature1
$(做一些改变)
$ hg commit
(输入提交消息)
$ cd ../project
$ hg pull ../feature1

通过集成的Web服务器共享版本库

$ hg serve &
$ cd ..
$ hg clone http://127.0.0.1:8000 project-clone

导出对文件的变更

$ cd project-clone
$(做一些改变)
$ hg commit
(输入提交消息)
$ hg export tip> ../changes.diff

从文件导入更改

$ cd ../project
$ hg import ../changes.diff

从服务器版本库中拉取(pull)变更

$ cd ../feature1
$ hg pull http://127.0.0.1:8000

在BitBucket上使用共享版本库

$(设置bitbucket repo)
$ hg push https://bitbucket.org/USER/REPO
(在提示中输入名称和密码)
$ hg pull https://bitbucket.org/USER/REPO

让我们继续实现有用的功能和更高级的工作流程。

高级工作流

退出不良修订版

用例

当你经常从其他人那里提取代码时,您可能会忽略一些不好的变更。一旦其他人从你那里获得了这一改更,你几乎没有机会彻底摆脱。

为解决任何真正分布式系统中的基本问题,Mercurial为您提供了退出(backout)命令,告诉Mercurial 创建一个可以撤销的不良提交。这样你就不必摆脱坏代码历史记录,但是你可以从新版本中删除。

注意:

基本命令不会重写历史记录。如果你想这样做,你需要激活mercurial附带的一些扩展。之后会讲到。

工作流

让我们假设不好的变更是版本3,并且版本库中已经有一个更新版本。要删除不良代码,您只需退出(backout)即可。这生成一个新的变更,扭转了不良变更。退出后,您可以将新更改合并到当前代码中。

$ hg backout 3
$ hg merge
(可能解决冲突)
$ hg commit
(输入提交消息。例如:"merged backout")

OK,你扭转了不良变更。但历史记录依然有记录(遵循“非必要,不重写历史”的原则),但它不再影响未来的代码。

协作功能开发

现在可以共享变更并在必要时撤消它们,继续深入,使用Mercurial进行协调开发

第一部分是一种简单的方式,可以一起开发功能,而无需每个开发人员跟踪多个功能副本。

用例

如果要将开发拆分为多个功能,则需要跟踪谁在哪个功能上工作以及在哪里获得哪些更改。

Mercurial通过提供命名分支可轻松实现。它们是主版本库的一部分,因此可供所有相关人员使用。同时,在某个分支上提交的更改不会与默认分支中的更改混合在一起,因此功能将保持独立,直到它们合并到默认分支中。

注意:

克隆版本库总是首先将您置于默认分支。

工作流程

当团队中的某个人想要开始编写某个功能而不会打扰其他功能时,他可以创建一个命名分支并在那里提交。当其他人想要加入时,他只是更新分支并提交。功能完成后,有人会将指定分支合并到默认分支中。

注意:

命名分支信息将永久存储在历史记录中,因此您始终可以查看添加了哪些更改的功能。如果您只想将临时分支作为历史记录上的短期标记,则可以使用“书签”。只需用hg bookmark 替换hg branch 并添加参数 -B bookmark_name 到hg pushhg pull
在命名分支中工作

创建分支

$ hg branch feature1
(做一些改变)
$ hg commit
(写提交消息)

更新到分支并在其中工作

$ hg update feature1
(做一些改变)
$ hg commit
(写提交消息)

现在,您可以提交(commit)拉取(pull)推送(push)合并(merge)(以及其他任何内容),就像在单独的版本库中工作一样。如果命名分支的历史是线性的并且你调用“hg merge”,Mercurial会要求明确的提供修订版,因为工作的分支没有任何要合并的内容。

合并分支

完成该功能后,将分支合并回默认分支。

$ hg update default
$ hg merge feature1
$ hg commit
(写提交消息)

使用hg branches查看活动分支。要将分支标记为非活动状态,例如因为您已完成功能的实现,可以将其关闭。已关闭的分支隐藏在hg brancheshg heads

$ hg update feature1
$ hg commit --close-branch -m "finished feature1"

这样现在可以轻松地将功能分开。

标记修订版

用例

现在你可以更轻松地编写单独的功能,因此你可能希望将某些修订版标记为适合使用(或类似)。例如你可能希望标记版本,或者只是将修订标记为已审核

对于这个Mercurial提供的标签功能。标签为修订版添加名称,并且是历史记录的一部分。您可以在提交后的几年内标记更改。标签包含添加时的信息,标签可以像任何其他提交的更改一样被拉取,推送和合并。

注意:

标签不能包含char“:”,因为该char用于指定多个修订版 - 请参阅“hg help revisions”。

注意:

要安全地标记修订版,您可以使用gpg扩展对标记进行签名。

工作流程

我们假设你想将版本3命名为“v0.1”。

添加标签

$ hg tag -r 3 v0.1

查看所有标签

$ hg tags

当你查看日志时,您现在会在变更集3中看到有标签的行。如果有人想要更新到标签的修订版,他可以使用您的标记名称

$ hg update v0.1

现在他将处于标记版本,可以从那里开始工作。

删除历史记录

用例

有时你将在版本库中进行更改,而你实际上你并不需要对其进行更改。

有许多高级选项可以删除它们,其中大多数都使用了很棒的扩展(Mercurial Queues是最常用的扩展),但在这个基本指南中,我们只用我们已经学过的命令来解决问题。但是我们会使用一个选项来克隆我们还不需要的东西。

当您需要删除隐藏在许多新变更下的变更时,此工作流程会变得不方便。如果你足够早地发现它们,你可以毫不费力地摆脱不良的修订版

工作流程

假设您想要删除修订版2,最高版本为3。

第一步是使用“--rev”选项进行克隆(clone):创建一个仅包含指定修订版本更改的克隆。由于您希望保留修订版1,因此你只用克隆修订版1

$ hg clone -r 1 project stripped 

现在,你可以从原始库中导出(export)变更集3 ,然后导入(import)到当前被剥离的项目中

$ cd project
$ hg export 3> ../changes.diff
$ cd ../stripped
$ hg import ../changes.diff

如果无法应用部分更改,你将在* .rej文件中看到该部分。如果你有* .rej文件,则必须手动包含或放弃更改

$ cat * .rej
(手动应用更改)
$ hg commit
(写提交消息)

hg export还包括提交消息,日期,提交者和类似的元数据,到此就算完成了。

注意:

删除历史记录将会改变修订版ID,再次拉取(pull)仍然会拉取到被删除的版本。这就是为什么重写历史只能是尚未公布的版本。

摘要

因此,现在您可以私下使用Mercurial,并以多种方式分享你的更改。

此外,你可以通过在版本库中创建一个可以撤销原始更改的更改,或者通过真正重写历史记录来删除不良更改,因此看起来似乎从未发生过更改。

您可以使用命名分支将单个版本库中的功能工作分开,并将标记添加到修订版本,这些修订版本是其他人的可见标记,可用于更新到标记的修订版本。

有了这个,我们可以得出我们的实用指南。