Git、Gerrit、Repo使用


三者各自功能
  1. gii,版本管理库,在git库中没有中心服务器的概念,真正的分布式。
  2. repo,repo就是多个git库的管理工具。如果是多个git库同时管理,可以使用repo。当然使用gerrit,就必须用repo。
  3. gerrit,提交审核代码,图形化的界面,简单的操作
使用三者管理代码流程
  1. repo init xxx初始化
  2. repo sync xxx同步要改动的项目
  3. 在该项目下面repo start xxx新建一个本地分支
  4. 做好改动以后git commit本地提交改动
  5. repo upload xxx将改动上传,等别人通过gerrit review
  6. review如果有需要改动的地方,那本地改好后,git commit –amend来保存新的修改
  7. repo upload 将新的改动上传
  8. 重复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 or git 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担任角色
  1. 和主代码服务器交互
  2. 用manifest.xml管理多个git仓库
  • repo init -u url -b branchname 初始化命令,主要干两件事
  1. 在当前目录里面下载安装 repo,因为最初从网上下载的那个 repo 文件并不是一个完整的 repo,它主要负责初始化工作,并且在初始化完成以后将命令移交给完整的 repo 来执行
  2. 根据命令中指定的地址(-u url)去下载项目的管理文件 manifest.xml ,这里 -b branchname 就是指的 manifest.xml 的相应 branch
  • repo sync 同步所有项目
  • repo sync project 主要干的事情是
  1. 同步 .repo/manifests/,再根据最新的manifest.xml来执行操作
  2. 找到想要下载项目,然后下载项目
  • 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流程
  1. 上传代码
  2. reviewer review 当change +2 就可以merge ,但是在+2之前,先有普通reviewer查看+1,以减轻主reviewer负担
  3. verify:可以人工完成,也可以用自动化工具,如自动化编译,自动化测试
  4. 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
安卓原生编译
  1. source ./build/envsetup.shor. ./build/envsetup.sh```</li>
    <li>```lunch
  2. 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时的含义一样。