Git、Gerrit、Repo使用
三者各自功能
- gii,版本管理库,在git库中没有中心服务器的概念,真正的分布式。
- repo,repo就是多个git库的管理工具。如果是多个git库同时管理,可以使用repo。当然使用gerrit,就必须用repo。
- gerrit,提交审核代码,图形化的界面,简单的操作
使用三者管理代码流程
- repo init xxx初始化
- repo sync xxx同步要改动的项目
- 在该项目下面repo start xxx新建一个本地分支
- 做好改动以后git commit本地提交改动
- repo upload xxx将改动上传,等别人通过gerrit review
- review如果有需要改动的地方,那本地改好后,git commit –amend来保存新的修改
- repo upload 将新的改动上传
- 重复5-7步,直到review通过,然后merge改动,完毕
Git 基础操作
git add 文件名
将当前更改或者新增的文件加入到Git的索引中
eg:git add readme.txt
git commit
提交当前工作空间的修改内容,,提交的时候必须用-m来输入一条提交信息- eg:
git commit -m "add model"
git status
仓库当前的状态- eg :
git status
git diff
命令
- eg:
git diff
比较的是工作目录(Working tree)和暂存区域快照(index)之间的差异,即修改之后还没有暂存起来的变化内容。 - eg:
git diff master..test
显示两个分支间的差异 - eg :
git diff master...test
‘master’,‘test’的共有 父分支和’test’分支之间的差异 - eg:
git diff --stat
统计那些文件被改动
git log
显示最近提交日志- eg:
git log
如果需要一行显示git log --pretty=oneline
git reset
版本回退- eg:
git reset --hard HEAD~X
会退到之前X版本
如果回退之后还想回来,可以使用
eg:git reset --hard "commit ID"
ID可以使用
eg:git reflog
查看历史命令获得ID git checkout -- file
丢弃工作区修改,撤销修改到最近一次git commit
orgit add
,即用版本库里的版本替换工作区的版本- eg:
git checkout -- readme.txt
注:不要遗忘 – git rm
删除版本库中文件- eg:
git rm
删除本地版本库文件,再使用git commit
提交
-
git checkout -b "xxx"
创建一个分支
eg:git checkout -b dev
创建dev分支并切换到dev分支,相当于
git branch dev
创建dev分支
git checkout dev
切换到dev分支
git branch -d dev
删除dev分支
git checkout . ``#本地所有修改的。没有的提交的,都返回到原来的状态
git branch
命令会列出所有分支,并在当前分支上标*
git merge
合并指定分支到当前分支- eg:
git merge dev
把dev分支合并到master分支上 git log --graph
可以看到分支合并图,如果git无法合并,必须先解决冲突才能提交。git stash
储藏当前工作现场,创建新分支修改紧急任务git stash
隐藏当前工作区git checkout master
切换到master分支git checkout -b issue
新建分支
解决完,并提交后git checkout dev
切回到以前工作分支git stash list
查看隐藏工作区git stash pop
恢复当前储藏的工作区
添加新功能最好新建feature分支,在上面开发,合并git pull
从其他的版本库(既可以是远程的也可以是本地的)将代码更新到本地- eg:
git pull origin master
origin版本库的代码更新到本地的master主枝 git push
:将本地commit的代码更新到远程版本库中- eg:
git push origin git push localbranch master:refs/for/master
将本地的代码更新到orgin的远程版本库中 git checkout HEAD <some file> [<some file>]
,清除工作目录树中的修改
打补丁
- 将commit打包成patch
- 修改代码
$ vi drivers/bluetooth/btusb.c
- 把代码添加到git管理仓库
git add .
- 提交修改
git commit -m "some message"
- 查看日志,获取到hash
git log
- 生成patch
git format-patch -s 1bbe3c8c19
- 或者–
git format-patch HEAD^
# 最近的1次commit的patch
- 测试,应用patch
- 检查patch文件
git apply --stat xxx.patch
- 查看是否能应用成功
git apply --check xxx.patch
- 应用patch
git am xxx.patch
注:1. 之前应,git am -abort
放弃之前am信息, 有可能会遇到 .git/rebase-apply still exists but mbox given
修改以及commit并且以及push的描述
- 修改最近一次的commit
git commit --amend
- 修改commit历史,
git rebase -i HEAD~X
or git rebase -i (commit -id)
接着会出现
pick:*******
pick:*******
pick:*******
ls
将pick改为edit就可以修改,利用`git commit –amend命令
最后git rebase --continue
搞定
如果需要删除已经push的可以将pick改为drop
Repo
- repo担任角色
- 和主代码服务器交互
- 用manifest.xml管理多个git仓库
repo init -u url -b branchname
初始化命令,主要干两件事
- 在当前目录里面下载安装 repo,因为最初从网上下载的那个 repo 文件并不是一个完整的 repo,它主要负责初始化工作,并且在初始化完成以后将命令移交给完整的 repo 来执行
- 根据命令中指定的地址(-u url)去下载项目的管理文件 manifest.xml ,这里 -b branchname 就是指的 manifest.xml 的相应 branch
repo sync
同步所有项目repo sync project
主要干的事情是
- 同步 .repo/manifests/,再根据最新的manifest.xml来执行操作
- 找到想要下载项目,然后下载项目
repo start branch project
- 如果希望这个 branch 是被 repo 管理起来的,那么我们就要使用
repo start
命令来新建一个 branch。
比如这个 branch 改好了后,你是需要上传到 gerrit 进行 review,那么就该使用repo start
。
如果只是一个临时实验性的分支的话,就无所谓了。但是使用repo start
也不会有什么坏处,所以放心的使用。
如果创建失败,可以使用 repo start branch project –all
删除 branch 的时候,依然是使用git branch -d branchname
repo upload project
- 当准备好一个 commit 以后,就需要把这个改动传到 gerrit 上面等待别人 review,就需要用到
repo upload
,如果branch不是repo start
创建,就必须使用repo start
创建新的branch,再使用git cherry-pick commitd
把刚才改动好的拿到repo创建的分支 repo forall -c git reset --hard HEAD
repo forall -p =c git branch
repo branches
查看当前有多少分支
Gerrit
- Review流程
- 上传代码
- reviewer review 当change +2 就可以merge ,但是在+2之前,先有普通reviewer查看+1,以减轻主reviewer负担
- verify:可以人工完成,也可以用自动化工具,如自动化编译,自动化测试
- merge:通过review之后,就可以merge change,保存到中心代码仓库。如果代码有冲突,需要手动处理再重新上传
- 从 gerrit 上面下载一个正在 review 的 change
- 有时候,需要将一个还没有merge 的 change 下载下来,这时,可以到一个 change 的页面,里面有 download 的地方,里面有很多下载选项。其中 cherry-pick 是比较常用的方式,你选了下载方式后,gerrit 会智能的生成相应的命令,只需要复制下来,然后在项目目录下面执行这个命令就可以了。
- 比较不同的 patch set
- 每个 change 通常需要重复“review - 改代码 - 上传新 patch”多次才能最终完成,每一次上传就称为一个 patch。gerrit 会方便的把你的改动内容列出来方便 review,而且你还可以选择比较不同的 patch set,在一个change 的页面,仔细看看还是比较容易找到地方。
- 查找 change
- gerrit 在页面右上角有一个搜索框,通过搜索匹配,你可以找到你想要的 change。比如 owner,project,status,branch 等等。比如:
status:open project:xxx
owener:”xxxxx
安卓原生编译
-
source ./build/envsetup.sh
or. ./build/envsetup.sh```</li>
<li>```lunch make ...
- 快捷方式
- croot:用于改变当前路径到Android根目录。
- m:用于从Android根目录开始编译。
- mm:用于编译当前目录下的所有模块。
- mmm:用于编译特定目录下的所有模块。
- cgrep:用于在C/C++文件中查找。
- jgrep:用于在Java文件中查找。
- resgrep:用于在资源文件中查找。
- godir:用于跳转到某个目录。
深入理解:http://blog.chinaunix.net/uid-9525959-id-4534319.html 注:repo用于管理多个git项目,同一产品可能包含多个git项目,不同的git项目集合,可能形成不同产品,通过repo可以实现方便的管理。repo主要包含repo配置信息、以及repo所管理的git项目集合。
对于所有git管理的项目,例如mygitproject,其中mygitproject/.git是git目录(或git库);mygitproject/中除.git之外的内容为git工作目录,来自相应git目录中的某个版本。
对于所有repo管理的项目,例如myrepoproject,其中myrepoproject/.repo是repo目录(或repo库);myrepoproject/中除.repo之外的内容为repo工作目录,来自相应repo目录中的某个版本。
1、repo init:
作用是下载或更新好repo配置和脚本集(相当于对repo配置和repo脚本集进行git pull,但是它还额外做了更多的事情),repo配置和脚本本身又是由git管理的,repo配置指定使用哪些git项目,脚本是repo命令本身的实现。
在空目录中执行这个目录后,会生成一个.repo目录,查看.repo目录,会看到有如下内容:
$ls .repo
manifests/ manifests.git/ manifest.xml repo/
具体解释如下:
(*).repo:此为repo目录,可用于提取相应项目工作目录到外面的repo工作目录。
(*).repo/manifests.git:此为repo配置信息的git库,不同版本包含不同配置信息,配置信息大致描述内容见后面。
(*).repo/manifests:此为repo配置信息的工作目录(将配置信息的工作目录和相应的实际git目录分离管理,并且配置信息中的.git目录实际只是指向实际git库的软连接),其中可能包含一个或多个xml文件描述的配置。每个xml文件是独立的一套配置,配置内容包括当前repo工作目录包含哪些git项目、所有git项目所处的默认公共分支、以及远端地址等。
(*).repo/manifest.xml:repo工作目录中的内容同一时刻只能采用manifests中的一个xml文件做为其配置,该文件就是其软连接,通过init的-m选项指定采用哪个文件;另外,同一xml文件也可能处于manifests库的不同版本或者不同分支,通过init的-b选项指定使用manifests中的哪个分支,每次init命令都会从服务器更新最新的配置。这里通过-m指定的manifests中的xml文件中,有两个需要注意:default.xml是稳定版,default_head.xml是开发版,开发版始终包含最新的内容。
(*).repo/repo:此为repo脚本集的git库,用于repo管理所需的各种脚本,repo的所有子命令就是其中的对应脚本实现。该脚本也通过git管理,.repo/repo/.git为对应的git目录。这里包含repo命令所需的所有子命令脚本实现,由python完成(我们可以在.repo/repo/subcmds中看到类似repo的init等的子命令脚本实现,如repo的init子命令即repo init,它由.repo/repo/subcmds/init.py实现),这个目录本身又由git来管理。不同的repo库或者不同版本的repo库,其repo命令实现会有些不同,所以也对应不同的repo脚本集,建议每次采用对应repo项目的最新的repo库做为其repo命令集实现。第一次使用repo时,采用的repo脚本实际是一个简单的repo的引导脚本,它既符合shell语法,又符合python语法,最终会将所需的具体脚本实现下载至最新的.repo/repo中,后面类似"repo init"、"repo sync"等脚本的实现,全都有这里的内容来实现。我们发现.repo/repo/repo,这个文件其实就是当前repo库中最新的repo引导脚本,可供其它没有使用过repo的用户做为repo的引导脚本来使用。
2、repo sync
作用是下载当前repo配置的所有项目,并生成对应的repo工作目录。执行之后,会看到.repo目录包含如下内容:
$ls .repo
manifests manifests.git manifest.xml projects repo
还有.repo外面也多出了许多目录。
也就是说,多出了一个projects目录,和.repo外面的许多目录,具体内容如下:
(*).repo/projects:此为repo所管理的所有git项目集,包含repo当前配置所指定的所有git项目对应的git目录。不同的清单文件(即manifest.xml)内容,指定不同的git项目集组合,表征不同的项目版本或者项目,而如上所述,manifest.xml文件的内容又由其指向的manifests中的、具体的分支下的、xml文件来决定。
().repo/…/:此为repo的工作区。在repo目录(即.repo)之外,根据repo配置(即.repo/manifest.xml文件),从.repo/projects/*中提取出指定分支的各个git项目(即.repo/projects中git项目的子集)的工作目录,形成repo工作目录,可供开发使用。其中每个git工作目录中的.git只是指向.repo/projects/*的软连接,在repo工作目录中的某个git工作目录更新相应的git库,其实最终会更新到.repo/projects中对应的git库。刚刚repo sync之后,当前工作目录不处于任何分支,其中的修改只能本地保存无法提交至远端,若想提交工作,需要先创建一个分支保存工作内容。
3、关于分支
以上描述,有几个分支的概念需要明确。
(1)repo分支:这里通过repo init -b ,中的-b所指定的分支,是manifests的分支,不同分支,其中的文件清单内容有所不同。
(2)清单文件指定的分支:通过清单文件manifest.xml中的default实体的revision属性,指定版本库默认的分支为revision属性值,该属性值做为repo sync之后工作目录中所有git项目的公共起点分支,也就是说,该manifest对应所有的git项目都有一个以revision属性值为名的分支,repo sync之后,在任意一个repo工作目录下的git库中,使用git branch或者repo start创建的分支,都是基于该git库中revision属性值为名的分支来创建。我们可以将这个分支设置为和repo分支类似的名字。
(3)git分支:除了repo管理的用于repo配置的repo分支,和用于设置工作目录起点的清单文件分支,每个工作目录对应的git库,也可设置自己的工作分支,和平时使用git时的含义一样。