协同开发漫游

前言

由于参与到合作项目中,在进行代码管理时不光要使用git,还需要使用gerrit、jenkins-CI等对提交进行审核与测试等,而对于包含多个组件的大型项目,需要使用repo对每个组件的git仓库进行分别管理。以下记录在使用repo + git + gerrit中的一些经验。

Git

参与项目中的模块开发,首先就是对当前自己参与模块的代码进行管理,如何管理自己的提交?如何管理自己与他人的提交?独立的模块作为项目中的一个子部分,自然是有一个独立的仓库进行管理,问题还是回到如何管理一个独立的仓库,在这个仓库下参与开发与进度管理,答案毋庸置疑是使用Git。
基础的操作包括配置账号git config、git init、git clone、git add、git commit、git push,当然了具体场景具体分析,参与公共项目或者公司项目的开发在配置上自然会有一些定制化(比不了在自己本机操作容易的很),但是基本操作流程还是如此。
一些基本操作:
git config --global user.name "Name"
git config --global user.email ddrh@example.com
git clone [URL]
git add [File]
git commit
git commit -m "description"
git push [remote host id] [local branch(optional)]:[remote branch]
Git三个区之间的关系:
回顾完基本操作,接下来就说说在参与协同项目开发时需经常需要用到的功能了,git本身博大精深,自己开发的时候很多设置未必能用上,所以git使用不在多还是在适合自己开发。对于协同开发,我总结为主要是做两件事情:历史交付漫游联合开发管理

历史交付漫游

git log --graph
通过查看历史交付情况掌握开发进度和记录,那自然是要使用git log命令,增加graph参数以树状图形式查看提交历史与merge情况,让自己对开发进度有大体了解。同时检索分支,查到每个提交的ID,可以方便的进行检索和回滚。

联合开发管理

同步最新提交

git pull --rebase
git pull就不多说了,为什么使用rebase?如果本地存在自己暂存还没merge的提交,使用rebase后可以自动让git在当前分支上将你的提交节点放到最前(当然有冲突先把冲突解决),这样就能保证你增加的新代码变到最新,能直接merge进分支中。所以,在push自己的commit前也同样进行这个操作,保证自己的提交到达最新,同时也能及时发现冲突项立马进行修改。

修改自己的同一次提交

git commit --amend
在上一次提交的基础上将这一次commit的内容整合到上次提交中,使用这个命令后出现的commit描述内容也会包含上一次commit时写的描述,可以在此基础上增加内容或者直接改动。使用这个命令可以起到对自己旧提交打补丁的效果,配合之后的gerrit使用非常好用。

提交树回滚

git reset --hard [ID] // 指定ID跳转
git reset --soft [ID] // 指定ID跳转
git reset --XXXX HEAD~N // 跳转向HEAD节点的前N个
git reset就是用来执行回滚操作,让你能够回滚到任何一次提交上,测试任何一次merge的提交,在定位新功能问题、对新旧功能进行对比时尤其好用。
主要的三个控制参数 --hard/mided/soft 从左到右,回滚程度依次减弱:
  • hard -> 工作区、暂存区、提交历史全部回滚
  • mixed -> 暂存区、提交历史回滚
  • soft -> 提交历史回滚
一般主要用hard和soft进行漫游,完全恢复环境和保留新功能,mixed视情况而定。

Gerrit

在联合开发时,可能会规定在merge代码前先审核代码,而gerrit则是一个常用的代码审核平台。

使用原因

  1. Gerrit是支持repo的代码审核系统。
  2. Gerrit以commit为单位合并,gitlab以branch为单位合并,大型开发涉及跨git仓库的commit,应该支持commit的聚类管理。
  3. Gerrit提供了topic用于标记commit之间的关系。
  4. Gerrit上每个commit有change-id(hook id),用于跟踪同一个commit的提交历史。

接入gerrit与hook id

尤其是在公司里,会将gerrit接入到提交系统中。在提交时,需要使用下面这种提交格式来将代码push到gerrit上:
git push origin HEAD:refs/for/[branch]
但是Gerrit更重要的是生成hook id(或者change-id)以管理提交。本质上就是一次commit的唯一id,该id不同于git的提交id,gerrit的commit其实是可以包含很多git commit的,只要这些commit都在同一个hook id下。

以topic进行提交

git push origin HEAD:refs/for/[branch]%topic=[topic]
首先要说明的是topic并非必须选项,gerrit是通过hook id记录提交记录的,topic只是一个标签。
  • 那么topic的作用是什么呢?
  • 为同一个功能的协同提交打上标签!
协同开发时,同一个功能的开发可能涉及到不同的功能模块的一次或者多次提交,通过topic将这些提交归档在同一个提交集合中,使得这些功能能够在jenkins上的功能测试中被同时索引,集成测试!
所以可见,协同开发时很多功能不仅仅是为了当前的开发节点,很大可能也是为了后续模块的使用方便,系统中的每个组件都不是孤立存在的。

给gerrit上自己的提交打补丁patch

发现自己提交到gerrit的提交存在问题需要修正,但是考虑到此次提交之后可能又有新的提交,牵一发而动全身,直接简单粗暴的abandon掉当前提交势必影响后继,这个时候就应该想办法在同一个gerrit提交上打补丁了。
  • 如何在同一个提交上修正呢?
  • 其本质其实是把所有的提交都放在具有同一个hook id的提交节点上,和git提交id还是不同的。
这就需要用到上面提到的git commit --amend,通过这个命令在本地先打好补丁。
在编辑commit内容时,上一次的hook id会显示在编辑内容中,无需编辑该hook id,编辑好自己新的commit内容进行提交,然后再push。这样一来新的提交修正会增加在同一个hook id的提交记录下,gerrit上的提交会显示你的旧提交打上了patch(有多个patch则会patch 2\3...)。
对于后继提交,可以直接在gerrit上使用rebase功能,将后继提交rebase到你打的patch的后继上去,其本质其实也是在后继节点的hook id上进行内容提交内容管理。

Repo

Repo是一个管理项目的工具,可以管理多个独立的git项目(模块)。
repo通过一个manifest文件(repo init后目录下的.repo/manifest.xml)描述本repo中包含哪些git项目。
在repo库下,可以使用repo命令同时操作所有git项目,也可以进入一个git项目对应的目录,单独运行git命令。
也正是由于一次改动可能会横跨多个git项目,因此需要引入topic的概念,将来自不同git项目的改动组织起来,此topic正是Gerrit提交时用到的topic!
而正如Gerrit使用原因第一点,Gerrit因为支持repo,所以在使用repo进行项目管理时会选择gerrit作为中间模块以管理提交。

初始化项目

repo init -u [URL] -b [branch] -m [XXX.xml] --repo-url [repo-url] \
--repo-branch=[repo-branch]
repo sync -j 4 // 同步每个仓库的提交树
repo forall -c git lfs pull // 同步每个库的大文件

操作每个仓库

repo forall -p -c [command]
-c: 具体的指令,一般为git指令
-p: 打印执行指令时的仓库路径,配合-c可以查看到指令出错的库
 
// 常见操作
repo forall -c git pull --rebase
repo forall -p -c git branch
repo forall -p -c git checkout [branch]
repo forall -c git lfs pull
posted @ 2022-01-26 23:17  ddrh  阅读(171)  评论(0)    收藏  举报