Chinaunix首页 | 论坛 | 博客
  • 博客访问: 255980
  • 博文数量: 22
  • 博客积分: 707
  • 博客等级: 上士
  • 技术积分: 458
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-28 20:45
文章分类

全部博文(22)

文章存档

2011年(12)

2010年(7)

2008年(3)

我的朋友

分类: LINUX

2011-09-08 15:58:54

hg简明教程

目录

 
 
   
   
   
   
 
   
 
 
 
 
   
  

摘要

2011年04月11日 by dangbinghoo

Copyright(c) dangbinghoo All rights reserved

1. 介绍

Mercurial(Hg)汞工具是个分布式的版本控制工具,不同于传统广泛使用的svn,cvs,vss这些集中式的 版本控制工具。 先区分下集中式和分布式的版本控制的不同:

  • 集中式

    仓库在一个服务器上,所有的更改都要提交到服务器,所以两个人并不能对同一个文件同时做出修改,这样,如果这两人必须等待相应文件是没有被锁定的,对于参与人数较多的较大项目,频繁的修改文件将需要大量的等待时间,很影响开发效率。

  • 分布式

    仓库在本地local,并不一定要放到集中的服务器上,对于文件所做的修改每次都是提交文件的修改集到本地仓库,所以服务器不在线并不影响工作。即便服务器丢失了仓库,因为每个本地仓库都有修改集,所以并不会丢失完所有信息。如果多人协作,修改集可以通过推送和拉取动作来在不同开发者的仓库之间同步。因为大部分操作是在本地,所以效率很高,对于多人同时完成一个项目就很适合了.

2. hg 的基础使用方法
2.1. 初始化一个仓库

初始化一个本地仓库很简单,先建立一个目录比如helloprj,然后使用hg init helloprj或者在helloprj 目录下面执行hg init就可以了。这时候hg会自己建立.hg目录,在里面初始化供它记录信息用的数据结构, 实际上hg会追踪你的源码文件,然后你每次的提交它都会保存到.hg里面的相应数据结构中。

$ hg init helloprj $
2.2. 对文件做出改动,提及更改,查看更改

接下来我们建立一个文件,并且在里面做些改动,然后提交

$ touch hello.c $ 编辑 hello.c

好了,使用 hg add 将hello.c加入跟踪

$ hg add hello.c adding hello.c

如果你是想跟踪整个工程的好多文件 在顶层目录直接执行 hd add就可以了.

这时候我们使用 hg status 命令来查看当前仓库的状态:

$ hg status A hello.c

这里看到大写字幕A,表示added,已添加hello.c文件

如果是?那就表示这是新建立的文件,还没有被hg纳入跟踪,那你就需要运行hg add命令了。

好了,我们再做些改动,再运行 hg status

$ hg status M hello.c

M表示文件已经修改,所以随时运行hg status命令就可以看到文件的改动情况。

接下来我们需要将我们做的修改提交起来,让hg做好差异化保存

$ hg commit -m "这是第一次提交,刚添加了hello.c文件"

然后我们再运行 hg status应该会看到什么也没有输出,这就表示你的仓库是干净的,没有新的改动出现。

刚才我们已经做了一次提交,这时候我们可以使用 hg log来看看

$ hg log 
 修改集: 0:bedf4c4d526d 
 标签: tip 用户: dangbinghoo  
 日期: Mon Apr 11 11:51:25 2011 +0800 
 摘要: 这是第一次提交,刚添加了hello.c文件

可以看到,hg log打印出来了本仓库做的改动记录, 本次修改集 id为 0,因为这是我们第一次修改。 摘要里会显示本次的提交理由,这里我们通常对所作的改动作以解释。

如果对仓库继续做出修改并提交,会出现新的修改集

$ hg log 
 修改集: 1:084bba0bd792 
 标签: tip 用户: dangbinghoo  
 日期: Mon Apr 11 11:56:07 2011 +0800 
 摘要: 修改了hello.c 
 修改集: 0:bedf4c4d526d 用户: dangbinghoo  
 日期: Mon Apr 11 11:51:25 2011 +0800 
 摘要: 这是第一次提交,刚添加了hello.c文件

可以看到多了一个 ID是1的修改集 ,这里我们就可以明白,hg 实际上会记录你每次的提交动作(commit),如果你只是对文件做了修改,却没有提交,那么修改集并不会产生。这时候你所的改动并不会被hg保存起来,所以你想悔改那是不可能的了。

注意

所以, 你一定要对你感觉正确的修改做出提交动作。

2.3. 克隆一个仓库,仓库之间修改集的推送和拉取操作

克隆一个仓库很简单,使用 hg clone就可以了,克隆操作会建立一个原仓库的副本

$ hg clone helloprj helloprj2 updating to branch default 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

然后使用我们之前的方法对helloprj2做出一些修改并且提交。

然后在helloprj仓库里执行拉取操作:

$ hg pull ../helloprj2 
 正在拉自 ../helloprj2 
 正在搜索修改 正在增加修改集 
 正在增加清单 正在增加文件改变 已增加 1 个修改集,包含 1 个改变,修改了 1 个文件 (run 'hg update' to get a working copy)

由于helloprj2的父仓库就是helloprj,在helloprj没有变动的时候拉取hellprj2只是一些更新的修改集, 并不会产生分支。

这个时候只是拉取了helloprj2的改动到这里,这时候本仓库的文件还没有改变,如果要应用刚才拉取的prj2的 改动就需要运行 hg update命令:

$ hg update 
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

然后我们再对helloprj2进行改动,然后试试push操作

$ hg push ../helloprj 
 正在推到 ../helloprj 
 正在搜索修改 
 正在增加修改集 
 正在增加清单 
 正在增加文件改变 
 已增加 1 个修改集,包含 1 个改变,修改了 1 个文件

这时候就可以在 helloprj仓库里执行 hg update来更新刚才推送的修改集。

$ hg update 
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

2.4. 分支与分支合并及冲突的解决

上一节我们只是对一个仓库进行了改动,然后来拉取和推送修改集,这一节我们将对同时对两个仓库都做修改,这就会产生分支,我们看看分支是如何产生的,以及如何合并分支。

在两个仓库里分别对hello.c文件的同一行做改动,然后分别commit,接着我们来在helloprj里面拉取 helloprj2的修改集:

$ hg pull ../helloprj2 
 正在拉自 ../helloprj2 
 正在搜索修改 
 正在增加修改集 
 正在增加清单 
 正在增加文件改变 
 已增加 1 个修改集,包含 1 个改变,修改了 1 个文件 (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge)

可以看到heads改变了,这时候我们可以使用 hg heads来查看下:

$ hg heads 
 修改集: 5:ada91e12af24 标签: tip 父亲: 3:7aec0e792b22 
 用户: dangbinghoo  
 日期: Mon Apr 11 14:22:03 2011 +0800 
 摘要: print 2 hello msg 
 修改集: 4:696888ef5d3e 
 用户: dangbinghoo  
 日期: Mon Apr 11 14:20:59 2011 +0800 
 摘要: added hello message output

可以看到 修改集5的父集为3,也就是说顶集改变了,这个时候就是说两个仓库的改动是两个分支了, 需要进行合并(merge)工作:

由于我们修改的是文件的同一行,有冲突发生,命令行运行了diff编辑器让我们手动来解决冲突, 选择你认可的修改,然后保存,

$ hg merge 
 merging hello.c 
 还有 3 个文件等待编辑 (gvimdiff:4736): GLib-GObject-CRITICAL **: g_object_ref: assertion `object->ref_count > 0' failed 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit)

由于我这里是linux系统,使用的gvim编辑器,所以hg调用了gvimdiff工具以进行手动合并。 然后我们看到提示信息 这是一个分支合并,不要忘记提交。

因为解决的分支合并的冲突是自己来修改文件,所以必须要提交了,按之前的方法提交即可。

这时候使用 hg log来查看信息:

$ hg log 
修改集: 6:96dac6a158e1 
标签: tip 父亲: 4:696888ef5d3e 
父亲: 5:ada91e12af24 
用户: dangbinghoo  
 日期: Mon Apr 11 14:28:43 2011 +0800 
摘要: branch merged! 
 修改集: 5:ada91e12af24 
父亲: 3:7aec0e792b22 
用户: dangbinghoo  
日期: Mon Apr 11 14:22:03 2011 +0800 
摘要: print 2 hello msg 
 修改集: 4:696888ef5d3e 
用户: dangbinghoo  
日期: Mon Apr 11 14:20:59 2011 +0800 
摘要: added hello message output 
 修改集: 3:7aec0e792b22 
用户: dangbinghoo  
日期: Mon Apr 11 13:43:06 2011 +0800 
摘要: complete main function 
 修改集: 2:80fd43d4a4fc 
用户: dangbinghoo  
日期: Mon Apr 11 13:35:57 2011 +0800 
摘要: 添加了一行代码 修改集: 1:084bba0bd792 
用户: dangbinghoo  
日期: Mon Apr 11 11:56:07 2011 +0800 
摘要: 修改了hello.c 修改集: 0:bedf4c4d526d 
用户: dangbinghoo  
 日期: Mon Apr 11 11:51:25 2011 +0800 
摘要: 这是第一次提交,刚添加了hello.c文件

可以看到分支的明显标志: 父亲 修改集的出现。


注意

这里我们修改的是同一个文件的同一行,用过diff的读者应该清楚,diff是足够智能的,如果你只是添加了代码,diff会忽略空行,并且清楚你是添加了代码,而不会把新添加一行也作为冲突,所以如果你在两个分支里所做的改动diff认为不冲突,那么合并就会自动完成,并不会让你手动来编辑.

3. hg 的网络协作
3.1. 仓库的网络地址

运行 hg help 我们可以看到 hg serve命令,hg 具有web服务器的作用,使用 hg serve可以很轻易 的将我们的仓库以网络的形势呈现出来.

运行 hg serve就可以了,如果你需要改动端口号,那么请使用-p参数,默认hg 使用8000端口,

$ hg serve

然后使用http://你的ip地址:8000就可以查看了,可以在里面看到分支的图形标示,及每次提交的更改 的diff显示。

$ hg serve -p 8080 127.0.0.1 
- - [11/Apr/2011 14:40:58] "GET / HTTP/1.1" 200 - 127.0.0.1 
- - [11/Apr/2011 14:40:58] "GET /static/style-paper.css HTTP/1.1" 200 - 127.0.0.1 
- - [11/Apr/2011 14:40:58] "GET /static/hglogo.png HTTP/1.1" 200 - 127.0.0.1 
- - [11/Apr/2011 14:40:58] "GET /static/hgicon.png HTTP/1.1" 200 - 127.0.0.1 
- - [11/Apr/2011 14:40:58] "GET /static/hgicon.png HTTP/1.1" 304
[注意] 注意

hg serve得到的网络地址适合在开发者之间进行快捷的共享和协同开发,如果你是要发布你的版本库,请使用我们架设的代码托管服务器,在服务器上的地址你需要使用的形式,http是不支持push操作的.

4.1. 使用网络地址进行拉取与推送

现在我们到仓库2中,并且再对hello.c做出修改,然后提交,接着我们进行网络推送

$ hg push 
 正在推到
 正在搜索修改 中止: push creates new remote heads on branch 'default'! (you should pull and merge or use push -f to force

可以看到网络推送是成功的,只是仓库2是分支,直接推送有冲突,默认并不直接覆盖。

不过现在我们应该清楚这个只需要在helloprj端进行pull操作然后merge即可。

到现在我们应该明白,其实hg的操作的确是在本地完成的,网络的仓库操作起来跟本地没什么区别,它只是 个本地外的仓库而已。

5. 在修改集直接切换 hg update -r

现在我们明白了hg的工作机理,实际上hg都是在记录修改集,所以从一个版本到另一个版本,修改集会变动,那么如果我们某次提交是错误的,我想换回到某次修改怎么办呢? hg update 加上-r参数即可,比较如要换到修改集3,那么使用

$ hg update -r 3

即可。 这时候我们使用 hg summary可以看到当前的修改集

$ hg summary 
 parent: 3:7aec0e792b22 complete main function branch: default commit: (clean)
 update: 2 new changesets (update)
6. 版本命名

在经过一段时间的开发之后,我们可能觉得某个修改集是一个值得发布的版本,那么我就可以打上标记 使用 hg tag命令即可:

比如:

$ hg tag -r 0 v0.01

这时候我们 hg log查看:

修改集: 0:bedf4c4d526d 
 标签: v0.01 
 用户: dangbinghoo  
 日期: Mon Apr 11 11:51:25 2011 +0800 
 摘要: 这是第一次提交,刚添加了hello.c文件
A. 更多高级特性的参考资料
A.1. 参考资料

以上是hg的基本操作流程,实际上hg的功能还很多,不过本教程只是个简明教程,完成和理解了本教程的内 容后自己查看相应的更具体详细的手册应该是容易的,所以这里推荐几个教程:

  1. Mercurial权威指南(《Mercurial: The Definitive Guide》)

  2. Mercurial Tutorial

  3. Mercurial与TortoiseHg使用入门教程 (windows 用户使用图形界面的请多关注此教程)

A.2. hg命令选项帮助

hg 带help系统,任何命令都可以使用 hg help 来获取其帮助,或者加上 -v选项来查看更详细的信息。

阅读(6734) | 评论(0) | 转发(3) |
给主人留下些什么吧!~~