日志标签 版本控制
回到未来 (3)
12月28日
9.3.3 时间旅行三
《回到未来-第三集》铁匠布朗博士手工打造了可以时光旅行的飞行火车,使用蒸汽作为动力。这款时间旅行火车更大,更安全,更舒适,适合一家四口外加宠物的时空旅行。与之对应本次实践也将采用“手工打造”:交互式变基。
回到未来 (2)
12月28日
9.3.2 时间旅行二
《回到未来-第二集》布朗博士改进的时间旅行车使用了未来科技,是陆天两用的飞车,而且燃料不再依赖核物质,而是使用无所不在的生活垃圾。而此次实践使用的工具也进行了升级,采用强大的git rebase 命令。

回到未来 (1)
12月28日
9.3 回到未来
电影《回到未来》(Back to future)第二集,老毕福偷走时光车,到过去(1955年)给了小毕福一本书,导致未来大变。
Git 这一台“时光机”也有这样的能力,或者说也会具有这样的行为。当更改历史提交(SHA1哈希值变更),即使后续提交的内容和属性都一致,但是因为后续提交 中有一个属性是父提交的SHA1哈希值,所以一个历史提交的改变会引起连锁变化,导致所有后续提交必然的发生变化,就会形成两条平行的时间线:一个是变更 前的提交时间线,另外一条是更改历史后新的提交时间线。
把此次实践比喻做一次电影(回到未来)拍摄的话,舞台依然是之前的DEMO版本库,而剧本是这样的。

Gerrit 代码审核服务器的工作流和原理
11月10日
谷歌 Android 开源项目在 Git 的使用上有两个重要的创新,一个是为多版本库协同而引入的 repo,这在之前我们已经详细讨论过。另外一个重要的创新就是 Gerrit —— 代码审核服务器。Gerrit 为 Git 引入的代码审核是强制性的,就是说除非特别的授权设置,向 Git 版本库的推送(Push)必须要经过 Gerrit 服务器,修订必须经过代码审核的一套工作流之后,才可能经批准并纳入正式代码库中…
阅读全部内容 »
Git 和 SVN 协同模型
11月4日
Topgit 原理及安装
10月28日
针对网友 dd 对 topgit 的疑问,我将写作中的 topgit 部分章节摘录如下。关于 dd 问到 windows 如何安装,应该可以在 cygwin 的环境下安装 topgit。我暂时还没有试验,因此并不是十分确定。Windows 下的 Git 我准备专门一章加以介绍,还没有开始呢。 ;-)
后记:Topgit在Windows上部署,参见: http://blog.ossxp.com/2011/03/2392/ 。
脱离 Gerrit 审核服务器,使用 repo
10月25日
Gerrit 代码审核服务器部署比较麻烦,更不要说因为 Gerrit 界面的学习和用户使用习惯的更改而带来的困难了。而且在一个固定的团队内部使用 repo 可能真的没有必要使用 Gerrit,因为团队成员都应该熟悉 Git 的操作,团队成员的编程能力都可信,单元测试质量由提交者保证,集成测试由单独的测试团队进行,即团队拥有一套完整、成型的研发工作流,Gerrit 并不适合引入。
脱离了 Gerrit 服务器,直接跟 Git 服务器打交道,repo 可以工作么?…
为了筹备中的 gitbook,我特意为 repo 增加了 repo push 的实现,效果和预期的一样好。
关于限制低版本 Subversion 写操作问题的回复
10月20日
有网友提问:
我在百度文库中看到贵公司发表的一篇文章《开源版本控制SVN 树冲突、目录丢失问题及解决机制探讨》。在文中有提到一个事情是,可以在svn的hook中设置禁止低于某版本的客户端提交操作,不知道具体的脚本是如何实现,还请指教,谢谢。
另外关于svn mergeinfo的问题,对于刚刚创建完的mergeinfo信息是纯在的,但是在开发过一段时间后,这个信息就丢失了,导致在合并的时候出现找不到祖先的错误。(备份库中的mergeinfo信息还是存在的)。不知道这个问题的发生时什么原因呢?
我认为并非因为有人使用了低版本(<1.5)的 SVN 客户端导致了 svn:mergeinfo 属性的丢失。因为低版本的 SVN 客户端,不了解 svn:mergeinfo 属性,又怎么能够会删除该属性呢?
使用低版本 SVN 客户端的副作用主要是在执行 merge 的过程中,不能将合并操作记录在 svn:mergeinfo 中,而不是会删除 svn:mergeinfo 属性。
实际上找到罪魁祸首很容易,因为 svn:mergeinfo 是受版本控制的属性,可以通过 svn log 命令查到何时,何人,何故删除了 svn:mergeinfo 属性。只需要执行下面的命令:
$ svn log -v PATH/TO/MERGE/ROOT/DIR
提到的钩子,对于你的情况:
- 配置邮件通知,及时获取版本库变更通知。
修改 post-commit 和 post-revprop-change 钩子脚本,在有代码/版本控制的属性/非版本控制的属性被修改的时候,发送邮件通知 - 禁止低版本客户端对 SVN 版本库执行写操作
修改 start-commit 脚本。在 SVNBOOK 中有详细的说明。 - 你也可以参照我写的 pySvnManager 项目,不过其中的钩子脚本为了支持图形化配置,比较复杂。
http://pysvnmanager.svn.sourceforge.net/viewvc/pysvnmanager/trunk/pysvnmanager/hooks/init/hook1.5/start-commit?revision=176&view=markup
Android 代码工作区转换为 Android 的Git库镜像
10月15日
最近的一段时间博客更新的会比较慢,因为在筹划一本关于 Git 的书。今天将其中的一节贴在这里。
Android 在版本库的管理上有两个重要的发明,一个是 repo ,用来管理 160 多个 git 代码库,另外一个是 Gerrit 代码审核服务器和基于 ssh 的 Git 服务器。因为 Android 代码库非常大,大约 1.6 GB,在开发团队的局域网内建立一个 Android 服务器镜像几乎是必须的。如果在以工作区方式同步 Android 代码后,想转换为镜像模式,repo 没有提供这样的能力。我在书中特意用一节来介绍如何 。。。
5.6.9 从 android 的工作区到代码库镜像
当执行repo sync 命令将 android 众多的版本库克隆到本地后,各个项目在工作区中的部署和实际在服务器端的部署是不同的。这个在之前介绍 repo 的索引库机制的时候,就已经介绍过了。
当 repo 工作区使用不带–mirror 的repo init -u 初始化并完成同步后,如果再次执行repo init 并附带了–mirror 参数,repo 会报错退出:”fatal: –mirror not supported on existing client”。实际上 “–mirror” 参数只能对尚未初始化的 repo 工作区执行。
那么如果之前没有用镜像的方法同步 Android 版本库,难道要为创建代码库镜像在重新执行一次 repo 同步么?要知道重新同步一份 Android 版本库是非常慢的。我自己就遇到了这个问题。
不过既然有 manifest.xml 文件,我们完全可以对工作区进行反向操作,将工作区转换为镜像服务器的结构。下面就是一个示例脚本,这个脚本利用了已有的 repo 代码进行实现,所以看着很简洁。 8-)
脚本work2mirror.py 如下:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os, sys, shutil
cwd = os.path.abspath( os.path.dirname( __file__ ) )
repodir = os.path.join( cwd, '.repo' )
S_repo = 'repo'
TRASHDIR = 'old_work_tree'
if not os.path.exists( os.path.join(repodir, S_repo) ):
print >> sys.stderr, "Must run under repo work_dir root."
sys.exit(1)
sys.path.insert( 0, os.path.join(repodir, S_repo) )
from manifest_xml import XmlManifest
manifest = XmlManifest( repodir )
if manifest.IsMirror:
print >> sys.stderr, "Already mirror, exit."
sys.exit(1)
trash = os.path.join( cwd, TRASHDIR )
for project in manifest.projects.itervalues():
# 移动旧的版本库路径到镜像模式下新的版本库路径
newgitdir = os.path.join( cwd, '%s.git' % project.name )
if os.path.exists( project.gitdir ) and project.gitdir != newgitdir:
if not os.path.exists( os.path.dirname(newgitdir) ):
os.makedirs( os.path.dirname(newgitdir) )
print "Rename %s to %s." % (project.gitdir, newgitdir)
os.rename( project.gitdir, newgitdir )
# 移动工作区到待删除目录
if project.worktree and os.path.exists( project.worktree ):
newworktree = os.path.join( trash, project.relpath )
if not os.path.exists( os.path.dirname(newworktree) ):
os.makedirs( os.path.dirname(newworktree) )
print "Move old worktree %s to %s." % (project.worktree, newworktree )
os.rename( project.worktree, newworktree )
if os.path.exists ( os.path.join( newgitdir, 'config' ) ):
# 修改版本库的配置
os.chdir( newgitdir )
os.system( "git config core.bare true" )
os.system( "git config remote.korg.fetch '+refs/heads/*:refs/heads/*'" )
# 删除 remotes 分支,因为作为版本库镜像不需要 remote 分支
if os.path.exists ( os.path.join( newgitdir, 'refs', 'remotes' ) ):
print "Delete " + os.path.join( newgitdir, 'refs', 'remotes' )
shutil.rmtree( os.path.join( newgitdir, 'refs', 'remotes' ) )
# 设置 menifest 为镜像
mp = manifest.manifestProject
mp.config.SetString('repo.mirror', 'true')
使用方法很简单,只要将脚本放在 Android 工作区下,执行就可以了。执行完毕会将原有工作区的目录移动到old_work_tree 子目录下,在确认原有工作区没有未提交的数据后,直接删除old_work_tree 即可。
$ python work2mirror.py



最新评论