研究android源码的都知道,在下载源码时,都是用repo init ,repo sync等命令去下载源码,repo内部是使用git进行版本控制的,之前没有仔细的了解,只知道跟着source.android.com的教程,当个打字员,然后编译,之后rom就出来了。让我进行这方面的研究的一个trigger是我现在进行的项目,需要对android的framework进行改动,我需要对音频模块进行修改,然后我小弟需要对另外一个模块进行修改,考虑到长久的代码管理及代码备份整合,有必要进行代码托管。之前我一直习惯使用svn,但是android那么庞大的数据量,用svn,再怎么多的硬盘也不够。先前就对git有所耳闻,但一直感觉它是个谜,没有勇气去触碰,趁着这个机会,也想好好学一学。
本文的目的是构建自己的android源码仓库,为此构建了一条龙的教程,进行了一系列服务端的安装配置,如repo,git,,gerrit,ssh rsa认证,并在此基础上从github上迁移Cyanogenmod仓库,达到最终的目的。
由于设备的原因,我现在代码都是从Cyanogenmod上拉取的。根据官方的教程,是从http://github.com/Cyanogenmod/android.git下载下来的,我之前以为它的代码全都是在那,用浏览器打开下,居然只有两个文件:README.mkdn和default.xml,仔细的看了下它的内容,尤其是default.xml,发现了端倪.
http://github.com/Cyanogenmod/android.git内容:
default.xml:
看着default.xml,仔细的跟源码进行对照,发现了其中的奥秘,也终于见识了git的分布式功能:git是个分布式的版本控制软件,它可以让你把代码分布在各个仓库,然后从各个仓库把各个项目取出来,这些仓库可以是你自己的,也可以是别人的。而repo正是对这些仓库进行统一的控制管理的工具。从default.xml,可以看到有
repo会从指定的版本仓库里下载里面的default.xml文件,进行解析,然后根据不同的
因此,我们可以修改里面的default.xml,更改部分的
repo在管理的时候,会使用gerrit进行Code Review,这个稍后再讲,不过《Git权威指南》的作者有一篇《脱离 Gerrit 审核服务器,使用 repo》,据称可以脱离Gerrit,很惭愧,按照他的教程我没有成功,也不想去深究了,求各路大牛指教。
repo的命令详见:http://source.android.com/source/using-repo.html
具体git的命令不详细描述了,有几个个人认为好的资源分享下:
《Pro Git》
《看日记学Git》
《Git权威指南》 --- 未读,听说口碑很好
Git的架设通常需要openssh server, Git, Gitosis, Apache2,我的服务端是ubuntu,这里用了两台机器:
sudo apt-get install git-core
sudo apt-get install python-setuptools
mkdir ~/src
cd ~/src
git clone https://github.com/tv42/gitosis.git
cd gitosis
sudo python setup.py install
sudo adduser git
sudo passwd git
ssh-keygen -t rsa
该命令会产生一对公私钥,然后将公钥复制到Server服务端
scp ~/.ssh/id_rsa.pub git@Server:/home/git
sudo -H -u git gitosis-init < /home/git/id_rsa.pub
然后,会在/home/git/repositories创建仓库目录,并且里面创建了一个管理员仓库,叫gitosis-admin,并且会把id_rsa.pub复制到keydir目录下
sudo chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update
git clone git@Server:repositories/gitosis-admin.git
可以通过修改gitosis-admin/gitosis.conf文件来管理Server上的仓库
[group gitosis-admin]
members [email protected]
writable = gitosis-admin
该文件可以创建不同的分组[group],分组有的members 设置不同的成员,然后通知对不同仓库的管理权限,在这里对gitosis-admin有写的权限。
cd ~
mkdir sample.git
git --bare init
[group sample]
members = [email protected]
writable = sample
members为用户,表示这些用户能够对sample进行写入。
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys
把Client上传的id_rsa.pub拷贝到 /home/git/.ssh/authorized_keys
cd /home/git
cp /home/git/id_rsa.pub .ssh/authorized_keys
重启ssh服务即可,如果有新的客户端想通过该方式访问Server,把它的rsa公钥拷贝添加到authorized_keys即可。之后我们用ssh登陆或者git clone就无需输入密码进行验证了。Git Server配置完毕。
sudo apt-get install apache2
激活代理模块
ln -s /etc/apache2/mods-available/proxy.conf /etc/apache2/mods-enable/proxy.conf
ln -s /etc/apache2/mods-available/proxy.load /etc/apache2/mods-enable/proxy.load
ln -s /etc/apache2/mods-available/proxy_http.load /etc/apache2/mods-enable/proxy_http.load
然后再/etc/apache2/httpd.conf中加入下面的内容(该文件初始为空),为了不跟之前的gitweb冲突,把该端口设置成8088
ServerName localhost
ProxyRequests Off
ProxyVia Off
ProxyPreserveHost On
Order deny,allow
Allow from all
AuthType Basic
AuthName "Gerrit Code Review"
AuthBasicProvider file
AuthUserFile /path/to/gerrit/etc/passwords
Require valid-user
ProxyPass / http://127.0.0.1:8080/
NameVirtualHost *:8088
Listen 8088
htpasswd -c /path/to/gerrit/etc/passwords "gerrit_fisrt_username" (第一次时要加-c,之后就不用了)
这里的gerrit_first_username就是用来登陆的用户名。
[httpd]
listenUrl = proxy-http://127.0.0.1:8080/
匹配。
ssh -p 29418 gerrit_fisrt_username@your-server-ip
会提示Permission denied(publickey),把刚才Client端上传的id_rsa.pub内容添加到gerrit中。注意这里要拷贝id_rsa.pub的全部内容。再次执行命令就是看到Welcome信息了。
remote: ERROR: You have not registered any email addresses.
我们可以停止Gerrit,进行手工的注册:
$ bin/gerrit.sh stop
$ java -jar bin/gerrit.war gsql
Welcome to Gerrit Code Review 2.1.6.1
(H2 1.2.134 (2010-04-23))
Type '\h' for help. Type '\r' to clear the buffer.
gerrit> select * from ACCOUNT_EXTERNAL_IDS;
ACCOUNT_ID | EMAIL_ADDRESS | PASSWORD | EXTERNAL_ID
-----------+------------------------+----------+------------------------------------------
1000000 | NULL | NULL | uuid:ac1b8a08-2dd1-4aa1-8449-8b2994dffaed
1000000 | NULL | NULL | username:demo
(2 rows; 23 ms)
gerrit> update ACCOUNT_EXTERNAL_IDS set EMAIL_ADDRESS='[email protected]' where ACCOUNT_ID=1000000;
UPDATE 2; 5 ms
gerrit> select * from ACCOUNT_EXTERNAL_IDS;
ACCOUNT_ID | EMAIL_ADDRESS | PASSWORD | EXTERNAL_ID
-----------+------------------------+----------+------------------------------------------
1000000 | [email protected] | NULL | uuid:ac1b8a08-2dd1-4aa1-8449-8b2994dffaed
1000000 | [email protected] | NULL | username:demo
(2 rows; 23 ms)
gerrit> \q
Bye
$ bin/gerrit.sh start
(此表来自于http://www.infoq.com/cn/articles/Gerrit-jenkins-hudson)
ssh -p 29418 git@your-server-ip gerrit create-project --name example.git
上述命令创建一个名为example的项目,在之前指定的Git目录里初始化一个空的代码库。如果已经有一个代码库了,Gerrit不允许创建同名代码库——但你可以先对它进行临时重命名,随后再把名字改回来。我们在Client端创建个克隆:
$ git clone ssh://git@your-server-ip:29418/example.git
我们可以向代码库进行提交和推送,就和其他Git系统一样:
$ cd example
$ echo hello > world
$ git add world
$ git commit -m "The World"
[master (root-commit) 06bf85e] The World
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 world
$ git push
No refs in common and none specified; doing nothing.
Perhaps you should specify a branch such as 'master'.
$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 217 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To ssh://me@localhost:29418/example.git
! [remote rejected] master -> master (prohibited by Gerrit)
error: failed to push some refs to 'ssh://demo@localhost:29418/example.git'
$ git config remote.origin.push refs/heads/*:refs/for/*
$ git push origin
Counting objects: 3, done.
Writing objects: 100% (3/3), 217 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To ssh://demo@localhost:29418/example.git
* [new branch] master -> refs/for/master
即可push成功。之后会在Gerrit上显示。
$ git checkout -b gingerbead
$ git push origin gingerbread
$ mkdir /home/git/mirror/
$ cd /home/git/mirror/
$ repo init -u http://github.com/CyanogenMod/android.git --mirror -b gingerbread
$ repo sync
在github中,如果不使用 -b,会出错。
$ mkdir /home/git/android/gingerbread
$ cd /home/git/android/gingerbread
$ repo init -u git@your-server-ip:mirror/CyanogenMod/android.git --mirror -b gingerbread
修改.repo/manifest.xml
- fetch="git://android.git.kernel.org/"
+ fetch=".."
$ repo sync
References: http://xxw8393.blog.163.com/blog/static/372568342011112111028926/
总的来讲,构建过程还是比较顺利的,遇到问题查看网上的信息进行各种分析,比较蛋疼的是那android源码的下载,在ubuntu上搭建的过程很简洁,很适合俺这种新手。不过在构建过程中,没有对Git有一定的了解碰到问题是比较郁闷的,比如那个Gerrit的上传及创建分支的问题,没有对它深入的理解,对那些命令估计也只是抄来抄去的,不能理解它的原理,我就属于这种,接下来要好好研究下。
版权所有,转载请注明出处