Subversion 用户眼中的 Git (5): 没有部分检出
Subversion 可以将整个库检出到工作区,也可以将某个目录检出到工作区。对于要使用一个庞大、臃肿的版本库的用户,部分检出是非常方便和实际的。
但是 Git 只能全部检出,不支持按照目录进行部分检出。
那么这是为什么呢? —— Subversion 用户问道。
Git 的确没有部分检出,这并不是说只有将整个库克隆下来才能查看文件。有很多 git 工具,提供直接浏览git库的功能,例如 gitweb, trac 的 git 版本库浏览, redmine 的 git 版本库浏览。
Git 为什么没有部分检出?
Git 以及其他分布式版本控制工具,据我所知,都没有实现部分检出的功能,至少没有实现如下的部分检出:
想像中的完美版本控制系统(但并不存在):
- 可以对一个大的版本库(分布式)进行部分检出,检出的也是一个独立的小版本库(分布式)
- 小的版本库也可以被克隆
- 小的版本库中的提交可以 PUSH 到大的版本库中
- 小的版本库可以从大的版本库 PULL 相应目录的改动内容
这种版本控制系统不能在分布式版本控制系统中实现,我认为:
- 大的版本库和部分检出的小的版本库,无法保证提交ID的一致性
因为分布式版本控制系统的提交ID是整个提交信息的SHA1哈希值,大版本库的提交经过裁减——部分检出后,内容变了,提交 ID 也应该改变才对。 - 因为大的版本库和小的版本库(部分检出)的提交ID不一致,导致两个版本库的 PULL 和 PUSH 无法操作
即不知道哪些提交相互对应,造成两个版本库间的PULL和PUSH无法进行 - 分布式版本控制系统中,提交作为一个整体存在,一个提交由于部分检出而人为分拆,造成混乱,如何合并呢?
Git 为什么没有必要实现 svn export 的功能?
Subversion 有一条命令:svn export ,可以将 subversion 版本库的一个目录下所有内容导出到指定的目录下。而 git 却无法找到类似命令。为什么呢?
- Subversion 需要 svn export 命令是因为该命令可以导出一个干净的目录,即不包含 .svn 目录(包含配置文件和文件原始拷贝)
- Git 只在根目录存在一个 .git 目录,此外在各个子目录下不再有任何控制目录存在,因此无须通过另外的命令导出一个纯粹的干净的原始文件目录
- 只需要用系统提供的文件/目录拷贝命令,即可以实现将干净的目录复制到指定的目录中
Git-submodule 可以实现版本库的模块化
如果说 git submodule 和部分检出的相似性,还不如说 git submodule 就是 svn:externals 翻版。
就是说 git submodule 可以将各个小的 git 版本库集合为一个大的版本库。如果不需要整个大的版本库的话,可以仅仅克隆某个小的 git 库。
Git-svn:集合 svn 的部分检出和 git 的便利
Git-svn 是 Subversion 的最佳伴侣,可以用 Git 来操作 Subversion 版本库。这带来一个非常有意思的副产品——部分检出:
- 可以用 git-svn 来对 Subversion 代码库的任何目录进行克隆,克隆出来的是一个git版本库
- 可以在部分克隆的版本库中用 Git 进行本地提交
- 部分克隆版本库中的本地提交可以提交到上游 Subversion 版本库的相应目录中
| 这篇文章由 蒋 鑫 于 2010年2月1日 - 21:00发表,分类于 Git, Subversion, 版本控制。您可以通过 RSS 2.0 来订阅对该条目的回复。 也可以发表评论或引用到你的网站。 |
还没有评论。
还没有引用。
Android repo 魔法
大约3天前 - 没有评论
Android 为企业提供一个新的市场,无论大企业,小企业都是处于同一个起跑线上。研究 Android 尤其是 Android 系统核心或者是驱动的开发,首先需要做的就是本地克隆建立一套 Android 版本库管理机制。
Android 使用 Git 作为代码管理工具,开发了 Gerrit 进行代码审核以便更好的对代码进行集中式管理,还开发了 Repo 命令行工具,对 Git 部分命令封装,将 百多个 Git 库有效的进行组织。要想克隆和管理这百多个 Git 库,还真不是一件简单的事情。
在研究 Repo 的过程中,发现很多文档在 Google Group 上,非“翻墙”不可看。非法的事情咱不干,直接阅读 repo 的代码吧。
创建本地 Android 版本库镜像的思路
如果了解了 Repo 的实现,参考 《Using Repo and Git》 , 建立一个本地的 android 版本库镜像还是不难的:
下载 repo bootstrap 脚本
$ curl http://android.git.kernel.org/repo >~/bin/repo
$ chmod a+x ~/bin/repo
$ export PATH=$PATH:~/bin
提供 –mirror 参数调用 repo 阅读全部内容 »

Repo——另一个Git协同模型
大约3天前 - 没有评论
Git 的神奇之处在于,你可以用很多不同的方式来使用它,而不像 Subversion,只有集中式一种方式。
最近又发现了一个 Git 新的协同模型 —— Repo,这个协同模型对于一个项目用到了多个Git版本库的协同开发非常有效。
实际上,这是上周在给一个团队做 “Git培训” 时,发现该团队在 Android 开发中,需要使用 Repo 这个工具来维护 Android 代码。于是花了些时间研究,补充了新的一章到讲义中…
Repo 是 Google Android 项目的附属工具,用于维护 Android 超级复杂的 Git 库(150多个独立的Git库)。虽然 repo 属于 android 项目,但 repo 本身可以独立使用,可以作为独立的工具,被任何项目使用。
用一句话概括 Repo: Repo 让分散的各自独立的 Git 版本库整合为一个整体。
不是有 git submodule 么?为什么还会出现一个 repo 呢?主要的原因,我认为有:
子模组不能指向Git库的某一分支,只是指向某个 commit
这对于项目发布没有问题,子模组指向 commit,即相当于固定于某个版本(里程碑)
但是对于开发非常不方便 。子模组固定于某个 commit,相当于处于 detached HEAD 状态,必须切换到分支才能更改。但是子模组对应于git库的哪一个分支,子模组的实现不能给出答案
主版本库和各个子版本库各自独立操作,不能整体的查看状态,查看differ
Repo 的实现很有趣,通过 repo 可以将本来各自独立的 Git 库在形式上整合为一个整体,可以用 repo 的命令进行整体操作。
通过一个 manifests git 阅读全部内容 »

Subversion管理后台增加对SVN容灾的支持
大约5天前 - 没有评论
群英汇Subversion版本控制系统提供的基本服务,实际上已经包含了简单的容灾实现:
在本机使用 gistore 进行数据备份
在备机上用 git pull 进行每日一次的数据同步
这个方法对于大多数公司,对于非核心数据的容灾备份已经足够,但是对于代码,不同的公司有着不同的敏感度,可能每日一次的备份就不合适了。
最近在给一个客户进行SVN版本控制系统的实施时,就碰到了SVN服务器间建立镜像和实时备份的需要
两个异地的开发团队,每个团队工作在不同的本地版本库,可能会参考(读取)异地不同版本库的内容
异地团队中间通过无线网桥互联,互联网桥的通讯质量易受到环境、气候的影响
如果两个异地的SVN服务器能够互做镜像,可以实现双机热备
一个团队可以在本地的主版本库中读写,一旦有数据写入本地版本库,就会同步到无线网桥另外一端的版本库。反之亦然。
由于本地还提供无线网桥另外一端版本库的镜像,因此访问远程版本库可以改用本地镜像进行访问,实现本地读取速度。
如果需要写入,配置 SVN反向代理,实现透明的远程写入。
Subversion可以使用 svnsync 这一工具实现版本库的远程镜像,但是如果使用手工配置,对于客户数量众多的版本库,难以维护。加之很多版本库本身很大,从头建立同步可能会非常缓慢。
我们通过在SVN管理后台增加了一对儿插件,实现了对SVN容灾(镜像)的图形化配置界面。
为同步用户建立用户帐号,并授权
在使用 svnsync 将本地版本库实时同步到远程版本库时,需要使用具有完全读写权限的帐号来完成对远程版本库的同步。
因此需要事先建立svn同步用户帐号,并在镜像的目标版本库对该帐号进行授权。
在用户管理平台,创建专门进行 svn 数据同步的用户帐号
不要将该用户加入任何用户组,即该用户禁止自行更改口令
因为该用户的口令更改,将破坏已经配置好的数据同步
使用SVN管理后台,对该用户授权,使其可以读写整个版本库(镜像的目标版本库)
镜像版本库的配置
为镜像版本库配置 ReadonlySvnMirror 插件,如下:
本例中,镜像SVN库的服务器地址为: http://svn2.moon.ossxp.com/svn/omed
该版本库只需要安装一个插件,即 ReadonlySvnMirror 插件
本例中,配置 Svnsync 管理员为 svnmirror
含义为只有用户 svnmirror 可以对该版本库进行提交,其它用户不能在该版本库中提交
源版本库的配置
为源版本库配置 SvnSyncMaster 插件
本例中,omed的主版本库地址为 http://svn.moon.ossxp.com/svn/omed,该版本库将向 http://svn2.moon.ossxp.com/svn/omed 发起实时的数据同步
本例中,发起同步的用户名为 svnmirror,该用户名和在svn2镜像服务器端的 ReadonlySvnMirror 插件配置的 svnsync 管理员用户名保持一致
用户口令是在用户管理平台为该用户(svnmirror)设置的口令,尽量选用长的口令
在“下游 SVN 镜像 URL”中输入镜像SVN版本库URL地址,每个一行。对于本例,输入地址:
http://svn2.moon.ossxp.com/svn/omed
镜像同步初始化
在SVN主版本库中安装 SvnSyncMaster 插件时,可能会遇到如下错误
403错误,无权访问版本库:可能是镜像服务器的版本库尚未对同步用户授权
403错误,无权访问版本库:可能是镜像服务器的版本库URL输入错误,错误的URL当然是没有授权的了
版本库尚未建立:如果镜像的目标版本库尚未建立,则不能在目标版本库记录同步信息也不能建立同步
版本库UUID不匹配:镜像初始化,会检查源版本库和目标版本库的UUID是否一致,如果不一致,可能会导致版本库同步的张冠李戴
证书不被信任或者证书签名者不被信任:换用 http 协议试试
其它
在配置相关插件之前,可以先通过拷贝方式将目标版本库复制到镜像服务器中
使用 scp 或者 rsync 的方式将主版本库复制到镜像服务器更直观,速度也更快
可以保证主版本库和镜像版本库的UUID保持一致
数据库复制完毕后,要修改镜像版本库的目录和文件的属主及权限。应该属于 www-data 用户
配置 SvnSyncMaster 插件,会自动根据当前镜像服务器端的版本号确定同步的进度,建立镜像关系
注意:不要在同步已经建立后再使用rsync。如果在镜像关系已经建立后,用rsync进行数据同步,会导致:
版本库插件配置被覆盖。因为版本库插件的配置位于版本库 conf/hooks.ini 文件中
版本库镜像信息被覆盖。因为版本库镜像信息保存在 rev0 的版本属性中
Gistore 备份回滚改用分支实现
大约1周前 - 没有评论
Gistore 备份的回滚原来采用的方法是,建立和回滚 Tag(里程碑):
当 master 分支的提交(备份)数量达到预设次数(缺省200次),建立一个 Tag,如 gistore/1
当名为 gistore/XXX 的 tag 的数量达到一定程度,进行回滚,即:
gistore/2 -> gistore/1
gistore/3 -> gistore/2
…
更改里程碑?!
正在写 Git 培训资料,开始写里程碑时,突然想到 gistore 实现中有更改里程碑的实现,这种实现是不好的:
里程碑在创建后,只在第一次同步(PULL)的时候,被获取
当里程碑修改后,其它人再执行 PULL 的时候,不会更新!
Gistore原来的实现,如果发生备份回滚,远程同步的服务器不能获取更新后的Tag。在镜像服务器有失去部分备份历史的危险。
新的备份回滚用分支来实现
分支名称为 gistore/1, gistore/2, …。数字越大的分支保存近期的备份,数字小的保存老的回滚备份。

爱上Git——《Git培训讲义》摘录
大约2周前 - 没有评论
群英汇的开源版本控制系统服务和咨询主要是基于Subversion,群英汇的开源项目管理系统平台主要集成的也是Subversion。但是我们公司(群英汇)内部的开发一直在使用Git,所以实际上,我们在Git上也有着丰富的使用和管理经验。
最近一个客户选择了我们提供Git的培训和部署服务,于是从上周开始着手准备《Git培训讲义》。
这个客户是有着实际的需求,才不得不从 Subversion 迁移到 Git,虽然只是公司的部分项目组。
《Git培训讲义》中开头有一章,我给它命名为“爱上Git”,抓眼球是其次,主要是先让用户能够立刻“爱上Git”。
爱上Git(1): 原位版本库创建
需求:要对部署的文件进行原位修改,记录变更并以 patch 形式导入正式版本库
要是使用SVN 该怎么办呢?
$ svnadmin create /path/to/repos
$ svn checkout file:///path/to/repos
$ svn add *
$ svn commit
思考: 引入.svn 目录,在 Web 服务器上的风险…
Git 就简单多了:
git init
git add .
git commit
爱上Git(2): 重写提交说明
需求:提交说明忘了添加bugid, 或者bugid 写错了,需要重写 commit log
要是使用SVN 该怎么办呢?
管理员开放版本属性编辑权限
svn ps –revprop -r HEAD svn:log “new log message…”
警告:不要改错版本…
Git 就简单多了:
对于当前提交
git ci –amend
对于历史提交
git rebase -i <commit-id>^
提示:使用 reword 子命令
爱上Git(3): 撤销提交
需求:提交的数据包含一个不应该检入的 .zip 大文件,浪费空间和检出时间
要是使用SVN 该怎么办呢?
管理员重整版本库
svnadmin dump
svndumpfilter
svnadmin 阅读全部内容 »
pySvnManager 0.5 升级指引
大约3周前 - 没有评论
对于不能提供 SSH 远程登录服务器的用户,可以参照本文进行 pySvnManager 的升级。关于 pySvnManager 的新功能,参照:《pySvnManager新功能:LDAP用户同步》
升级的步骤简单的说就是:备份 -> 软件升级 -> 重启服务
数据备份
你可以备份 /opt/pysvnmanager 整个目录(主要是下面的 sites 目录)。
$ sudo cp -a /opt/pysvnmanager /opt/pysvnmanager.old
如果使用 gistore 备份,也可以执行命令:
$ sudo gistore commit-all -v
软件升级
首先更新 APT 源,以便 Debian/Ubuntu 能够感知上游软件的更新。
$ sudo aptitude update
升级 pysvnmanager
$ sudo aptitude install pysvnmanager
升级过程中 aptitude 命令可能会显示或者询问一些升级策略。例如:提示安装 pysvnmanager-deploy-virt 包,并卸载原来安装的 pysvnmanager-deploy-sys 包。这是因为:
pysvnmanger 软件包实际上包含了下列组件包:
pysvnmanager :不包含实际数据,仅用于确立包的依赖关系。必须安装 pysvnmanager-common 包,以及pysvnmanager-deploy-sys 或者 pysvnmanager-deploy-virt 包中的任何一个。
pysvnmanager-common : 主要的源代码和执行脚本都在这个包中。
pysvnmanager-deploy-sys : 使用系统提供的第三方软件包,使得 阅读全部内容 »

pySvnManager 新功能:LDAP用户同步
大约3周前 - 没有评论
pySvnManager 升级到 0.5 版本,引入了数据库支持,数据库主要用于保存和 LDAP 用户帐号同步的用户帐号信息。
数据库采用 sqlite 数据库(如果需要也可以使用其它类型数据库),无须手动创建数据库,在 pySvnManager 运行时,会根据需要自动创建数据库。
在没有使用 LDAP 用户信息之前,pySvnManager 是读取 SVN 授权文件,从该授权文件中获取用户名单并显示。
可以看出这种实现的问题是:
在权限检查的用户列表中,只能看到用户登录ID,而看不到用户 ID 对应的用户名
显示的用户帐号很少(只有在 SVN 授权文件中引用的用户帐号才能显示)
为新用户授权,如果用户不在授权文件中,需要手工输入用户名,容易出错。
pySvnManager 0.5 增加了内置数据库和LDAP用户同步功能之后,再看 pySvnManager 中显示的用户列表:
你会发现新版本的用户列表(已经完成和LDAP同步):
除了显示用户ID外,还显示用户名
显示的用户多了很多,除了在 SVN 授权文件中引用到的用户外,LDAP 中授权的 SVN 用户也显示出来了
在为新用户授权时,不必手工输入用户,只需要进行一次 LDAP 用户同步,用户帐号信息自动显示出来。
那么如何进行LADP 同步呢?
我们把 LDAP 用户同步的按钮放在“角色管理”界面,只要点击其中的“和LDAP用户同步”图标按钮,自动完成同步。
其它改进还包括:更好的 IE6 支持,UI 的重新设计等等。我们会陆续协助客户完成软件升级。
用户手册也已经更新,参见: 《pySvnManager 用户手册》
关于如何升级到新版本的 pySvnManager,参照《pySvnManager 0.5 升级指引》
解决 gistore 备份数据中的 git 库(submodule)的备份
大约1月前 - 没有评论
昨天在从客户现场回公司的路上,想明白了 Gistore 备份出现的 AM 标识的备份数据就是含有变更的子模组。
之前 Gistore 不能解决的一个备份问题是,当备份的数据中包含 git 库,备份数据将不会保存在 gistore 版本库中,而是以 submodule 方式加入备份库。实际的效果是,数据没有备份下来。例如:
安装了 etckeeper,用于维护 /etc 下配置文件的变更。实际上 /etc 目录本身已经是一个 git 库了
如果在 gistore 任务建立前,/etc 目录已经 git 化,则不能有效的对 /etc 进行备份
某个备份数据的目录,被人为的 git 化。这可能是在 hacking 时遗留的 git 库
我在改动服务器的某些数据(如界面模板等),经常将目录 git 化,然后再修改/比较/提交
如果不能有效的对 git化的备份目录进行备份,肯定会收到惩罚。
在最早的实现中,只是在备份之后的后处理(post_check)查找以 git 子模组方式添加的目录,并打出相应的警告信息。如何能够自动进行处理,一直排在工作队列中,昨天晚上开始了修改。
检查子模组
首先要找出哪些目录是以子模组方式添加的。最开始想到了从状态中找出 AM 标识的子模组,进行修改,但是存在问题:1. 添加没有变更的git化的目录,不会显示为 AM(添加且含修改),而显示为 A(添加)。2. 不能有效的发现 gistore 版本库中已经提交数据中以 git 子模组方式添加的目录。
于是采用分析 git submodules status 命令的输出,确定子模组。不过这个命令需要多次迭代执行(遇到无 .submodules匹配报错退出),才能找到所有的子模组。
重新以普通目录和文件方式添加子模组
首先删除已经提交的按照子模组方式保存的目录,重新添加不能直接添加子模组目录,否则仍会按照子模组方式添加。采用的方法是:
删除已经按照子模组方式添加的目录
git –git-dir=repo.git rm 阅读全部内容 »
Gistore(基于 git 的数据备份软件)升级至 0.2.x
大约1月前 - 没有评论
在 10年1月份的一篇 Gistore 发布声明的博客中 ,我介绍了我们自己开发的一个用户数据备份的小工具 Gistore。
是什么原因让我们开发备份工具呢?这是因为:
我们公司的数据备份的需要
客户数据备份需要更好用的软件
rdiff-backup 和 flexbackup 的备份方案不够好
实际上 rdiff-backup 用做数据备份,已经足够好了,你可以从我们公司的维基中看到 rdiff-backup 的使用方法:
《存储可靠性、数据备份和恢复》
但是 rdiff-backup 的解决方案的问题是:
命令难记,包括我自己在数据恢复的时候还要一遍一遍的查阅文档
之所以命令难记,实际上是因为备份工具本身的使用率很低,只有在灾难恢复时候会用到,所以命令不熟悉是一定的。
数据的异地镜像比较复杂,需要引入其它工具
为什么不用 Git 开发一款工具呢?
Git 的命令天天在用,实在是太熟悉了
Git 的数据同步太方便了,在同步过程能够实时查看进度
此次 Gistore 升级,解决了半年多的使用过程中积累问题,并且增加了易用性。
备份时的提交说明简单、易懂、有用
例如我们公司一台服务器最近的备份日志:
/backup/gistore/default$ git –git-dir=repo.git log
commit cf23ccd2e51ce04941871cae0e1062b685fa4640
Author: root <root@ossxp.com>
Date: Thu Jul 29 16:20:52 2010 +0800
Changes summary: total= 29, A: 7, D: 1, M: 21
———————————————
A => opt/redmine/files/100729102244_add_redmine_task_repository.png, opt/redmine/files/100729102301_setting_redmine_task_repository.png, opt/redmine
D => opt/mailman/lists/jobs/digest.mbox
M => 阅读全部内容 »
Git 服务器软件 gitosis 的改进
大约1月前 - 没有评论
群英汇内部的 Git 服务器使用 gitosis 软件架设,能够实现针对版本库的授权,以及基于公钥的安全的无口令的版本库访问。
在 Gitosis 的使用过程中,我们根据需要对其进行了改进,以满足我们对授权和版本库管理上的需求:
增加了管理员角色,只有管理员才能够创建版本库
原来的实现只有 readonly 和 writable 两种权限,其中 writable 可以创建版本库。
我们权限分为三级:read/write/admin。拥有管理员(admin)权限,可以创建版本库,并自动具有读(read)写(write)权限
拥有写(write)权限也包含读(read)的权限
如果没有设置权限,禁止范围版本库
版本库匹配支持通配符,这样在授权的时候,可以用通配符为某个目录下的所有代码库授权
原有的实现,在配置文件中必须写入完整的版本库名称(路径)
当我们增加了管理员的概念后,增加通配符,就可以为特定的命名空间进行授权,而无须因为某个管理员要建库,还要修改授权文件
有了通配符后,读写权限的设置也更为简单。
通配符支持?,* 和 **。问号匹配一个字符,* 匹配任意字符(路径/字符除外),两个星号匹配包括路径分割符在内所有字符
增加了版本库路径映射的可用性。版本库路径映射在代码库重构中非常有用
增加了正则表达式匹配路径和替换映射
在权限检查的路径命中之后也检查路径映射,可以减轻错误配置的可能性
创建版本库只有写操作才进行,读操作不创建版本库
原来的实现支持即时创建版本库,在读取一个不存在的版本库时自动创建
读操作创建库,这会导致很多因为版本库克隆时路径输入错误导致错误建库
我们更改后,只允许在写版本库时并且具有 admin 权限才初始化新的代码库
版本库名称中允许出现中文(UTF-8)
基本上版本库命名都用英文字符,不过有个客户提出来支持中文版本库,我们就添加了这个支持
下面,拿一个配置文件来说明:
1 [gitosis]
2 repositories = /gitroot
3 #loglevel=DEBUG
4 gitweb = yes
5 daemon = no
[gitosis] 小节配置的是全局参数,可以在各个版本库自定义的小节中对其覆盖
第二行设置版本库缺省的根目录,git 版本库一般都会建在这个目录的下面
gitweb 和 daemon 用于设置和 gitweb 和 gitdaemon 的整合
7 [group gitosis-admin]
8 write 阅读全部内容 »
