杰里6916
In the past week I’ve started using Gerrit for all development on SQLAlchemy, including for pull requests, feature branch development, and bug fixes across maintenance branches. I was first introduced to Gerrit through my involvement in the Openstack project, where initially I was completely bewildered by it. Eventually, I figured out roughly enough what was going on to be productive with it and to ultimately prefer it for adding code changes to a project. But making the big leap of actually moving SQLAlchemy and my other key projects over to it required the extra effort of learning Gerrit a little more fundamentally as well as installing and integrating it with SQLAlchemy’s existing workflows.
在过去的一周中,我开始将Gerrit用于SQLAlchemy的所有开发,包括拉取请求,功能分支开发以及跨维护分支的错误修复。 我最初是通过参与Openstack项目而被介绍给Gerrit的,最初我对此完全感到困惑。 最终,我大致弄清楚了要进行哪些工作才能产生成果,并最终更喜欢它为项目添加代码更改。 但是,要实现将SQLAlchemy和我的其他关键项目实际转移到其中的巨大飞跃,需要付出更多的努力,从根本上学习Gerrit,并将其安装并集成到SQLAlchemy的现有工作流程中。
I don’t consider myself to be any authority on Gerrit, so my description here is based on my working impression of what it does; the details may not be entirely accurate. Gerrit is a “code review” tool, intended to allow collaboration around code changes targeted at a project. At that level, what Gerrit is doing can be compared to a pull request – allows proposal of a change, shows you how it’s different from what’s there already, allows comments on the change including against specific code, and then provides workflow to allow the change to be merged into the code repository. For those familiar with pull requests, this seems exactly the same, yet while I’ve always been very unsatisifed with pull requests for a long time, I am completely satisifed with Gerrit’s model. So to understand that requires more understanding of Gerrit.
我不认为自己是Gerrit的权威,因此此处的描述是基于我对Gerrit所做工作的印象。 详细信息可能并不完全准确。 Gerrit是一个“代码审查”工具,旨在允许围绕针对项目的代码更改进行协作。 在此级别上,可以将Gerrit的操作与请求请求进行比较–允许提出更改建议,向您显示更改与现有更改有何不同,允许对更改进行注释(包括针对特定代码),然后提供工作流程以允许更改合并到代码存储库中。 对于熟悉请求请求的人来说,这似乎是完全一样的,但是尽管我一直很不满意请求请求,但我对Gerrit的模型完全满意。 因此要了解这一点,需要对Gerrit有更多的了解。
At its core, Gerrit is maintaining a set of git repositories that are basically mirrors of your projects’ actual git repositories. Then, it adds some additional, non-mirrored (e.g. only to its local copy) reference paths to these git repositories such that you can push commits to them which represent Code Reviews. These commits resemble feature branches in that they are branched off of “master” or another maintenance branch, but the way we work with them is different. The most immediate difference is that unlike a traditional feature branch, the individual “code review” is always a single containing the entire new feature all at once, whereas a feature branch may consist of any number of commits. In order to allow additional changes and refinements to the “Code Review” as it proceeds, you create a brand new changeset that encompasses the previous changeset completely, plus your new changes. Since there is no longer a linear history in Git between these refinements, Gerrit adds an additional “Change-Id” identifier to the commit message which is how Gerrit keeps track of each change in a code review. So instead of a long-lived feature branch that changes by adding new revisions to the end of it, you have a series of discrete all-at-once commits, each one containing the whole feature at once.
Gerrit的核心是维护一组git仓库,这些仓库基本上是项目的实际git仓库的镜像。 然后,它向这些git存储库添加一些其他的非镜像(例如,仅到其本地副本)引用路径,以便您可以将提交推送到代表代码评论的提交。 这些提交类似于功能分支,因为它们是从“主”分支或另一个维护分支分支出来的,但是我们使用它们的方式是不同的。 最直接的区别是,与传统功能分支不同,单独的“代码审阅”始终是一次包含全部新功能的单个代码,而功能分支可以包含任意数量的提交。 为了允许对“代码审查”进行进一步的更改和完善,您需要创建一个全新的变更集,该变更集应完全包含以前的变更集以及新的变更。 由于这些改进之间在Git中不再存在线性历史记录,因此Gerrit在提交消息中添加了一个额外的“ Change-Id”标识符,这是Gerrit在代码审查中跟踪每个更改的方式。 因此,您可以使用一系列离散的一次性提交,而不是通过在其末尾添加新修订来更改的长期功能分支,每个提交一次包含整个功能。
In ASCII art parlance, the traditional Git branching model, also used by pull requests, can be seen like this:
用ASCII术语来说,传统的Git分支模型(也被pull请求使用)可以看成这样:
rev 1 -> rev 2 -> rev 3 -> rev 4 -> rev 5 -> master
|
+-> rev 3a -> rev 3b -> rev 3c -> feature branch
rev 1 -> rev 2 -> rev 3 -> rev 4 -> rev 5 -> master
|
+-> rev 3a -> rev 3b -> rev 3c -> feature branch
Above, the feature branch is forked off from the code at some point, and as development continues, a new revision is added to the feature branch. The multiple commits of the feature branch will eventually be merged into master, either using a traditional merge, or by “rebasing” the feature branch onto the top of master.
上面,功能分支有时会从代码中分叉出来,并且随着开发的继续,新的修订版将添加到功能分支。 特征分支的多个提交最终将使用传统的合并或通过将特征分支“重新定基”到母版顶部而合并到母版中。
In Gerrit, the open-ended nature of Git is taken advantage of in an entirely different way, and the mapping of Gerrit to Git might look more like this:
在Gerrit中,以完全不同的方式利用了Git的开放性,并且Gerrit到Git的映射可能更像这样:
The above model would be difficult to work with using Git alone; Gerrit maintains the list of changesets conforming to a Change Id in its own database, and provides a full blown GUI and command line API on top so that the history of development of the “Feature” is very clear and easy to work with.
仅使用Git很难使用上述模型; Gerrit会在自己的数据库中维护符合变更ID的变更集列表,并在顶部提供完整的GUI和命令行API,以便“功能”的开发历史非常清晰且易于使用。
The major caveat with this whole approach is that there’s a non-trivial conceptual hill to climb in order to use it, particularly if you’re not accustomed to “git rebase” (as I wasn’t). When we are in our code change that we’ve pushed as a code review, and we want to revise it and push it up as a new version of that code review, we need to replace the old commit with the new one, not add it on as additional history. The most fundamental thing this means is that instead of saying git commit, we have to say, git commit --amend, meaning, squash our current changes into the most recent commit. The hash of the recent commit is replaced with a brand new one, and the old commit is essentially floating, except for the fact that Gerrit will track it.
整个方法的主要警告是,要使用它,需要攀登一个不平凡的概念性山丘,特别是如果您不习惯“ git rebase”(因为我不是)。 当我们进行代码更改时,已将其推送为代码审查,并且我们希望对其进行修改并将其作为该代码审查的新版本进行推送,我们需要用新的提交替换旧的提交,而不是添加作为其他历史记录。 最根本的还是这意味着,而不是说git的承诺 ,我们不得不说,git的承诺--amend,这意味着,壁球我们当前转变为最近的提交。 最近的提交的哈希值被全新的哈希替换,并且旧的提交基本上是浮动的,但Gerrit会跟踪它。
When we amend a single commit, we get the same commit message and we basically leave it alone; the commit message represents what the change will be a whole, not the little adjustment we’re making here. The commentary about adjustments to our feature occurs in the comment stream on the review itself. With Gerrit’s approach, you no longer have commits like, “fix whitespace”, “add test”, “add documentation” – at the end of the day there will be just one commit message with, “Add Feature XYZ; XYZ does QPR …”. I consider that an advantage, because intermediary commits within a feature branch like “fix whitespace” are really just noise; I don’t miss them.
当我们修改单个提交时,我们会得到相同的提交消息,并且基本上将其保留下来。 提交消息表示更改将是一个整体,而不是我们在此所做的小调整。 有关我们功能调整的评论出现在评论本身的评论流中。 使用Gerrit的方法,您将不再拥有诸如“修复空白”,“添加测试”,“添加文档”之类的提交-最终,只有一条提交消息带有“添加功能XYZ; XYZ执行QPR…”。 我认为这是一个优势,因为中介在诸如“固定空白”之类的功能分支中提交的内容实际上只是噪音; 我不会想念他们的。
The other thing that has to be dealt with is that Gerrit won’t allow you to push up a code review that can’t be cleanly merged into the working branch it will be a part of. Again, this is a conceptually odd thing to adjust to but when you start doing it you realize what a great idea it is; when we work with tradtional feature branches and pull requests, there’s always that time when we realize we’ve fallen so far behind master, and oh now we have to merge master into our branch, and fix all the conflicts, so that we can merge back up later without making a huge mess.
必须处理的另一件事是,Gerrit不允许您推送无法完全合并到将成为其中一部分的工作分支中的代码审查。 同样,从概念上来说,这是一件很奇怪的事情,但是当您开始这样做时,您会意识到这是个好主意。 当我们使用传统功能分支并提取请求时,总有一次我们意识到我们已经远远落后于master,哦,现在我们必须将master合并到我们的分支中,并解决所有冲突,以便我们可以合并稍后备份,不会造成大麻烦。
With Gerrit’s approach, nothing ever gets pushed up that can’t be immediately merged, which means if you’re targeting a project that has a lot of activity, you’ll find yourself having to rebase your code reviews every time – but the key word here is “rebase”. Instead of merging master back into our feature branch, we are doing a straight up rebase of our single commit against the state of master; and because there’s only one commit to deal with, this is usually a very simple process – we aren’t burdened with trying to knit the changesets together in just the right way, or worrying about awkward merge artifacts cluttering up our feature branch forever; we flatten everything, and all the clutter of how we merged things together is discarded. As long as you’re comfortable with “git rebase”, it’s a predictable and consistent process. If you are using Gerrit for any amount of time, you will be very comfortable with rebasing :).
使用Gerrit的方法,没有任何事情会立即被合并,这意味着如果您要针对一个活动很多的项目,您将发现自己每次都必须重新编写代码审查的基础,但是关键这里的单词是“ rebase”。 我们没有将master合并回我们的功能分支,而是针对master状态对单个提交进行了直接的基础调整。 而且由于只有一个提交要处理,因此这通常是一个非常简单的过程–我们不必以正确的方式将变更集编织在一起,也不必担心笨拙的合并工件会永远困扰我们的功能分支; 我们将一切都弄平了,而我们将事物合并在一起的所有杂物都被丢弃了。 只要您对“ git rebase”感到满意,这是一个可预测且一致的过程。 如果您在任何时间使用Gerrit,您都会对重新定级非常满意:)。
The advantages to the above Gerrit model are in my opinion huge wins, including:
我认为上述Gerrit模型的优势是巨大的胜利,其中包括:
Overall, with Gerrit I now have a single, consistent way to do all new code; all of my feature branches, all of my random .patch files sitting in my home directory, pull requests from github or bitbucket; all of it goes straight into Gerrit where I have them all under one interface and where changes, history, code review, workflow, and comments on them are permanent, without creating any branch junk in my main git repo!
总的来说,有了Gerrit,我现在有一个一致的方法来编写所有新代码。 我所有的功能分支,我所有的随机.patch文件都位于我的主目录中,从github或bitbucket提取请求; 所有这些都直接进入Gerrit,在这里我可以将它们全部放在一个界面下,并且对它们的更改,历史记录,代码审查,工作流和注释是永久的,而无需在我的主要git repo中创建任何分支垃圾!
Gerrit has a ton more features as well, including an extremely detailed permissioning model which you can map to specific paths in each git repo; a Lucene-powered search feature, a replication engine so that changes to the local git repo can be pushed anywhere else; it is itself a full blown http and ssh server for the git repositories as well as for its command-line and GUI interfaces, and generally has all-around industrial style features.
Gerrit还具有许多其他功能,包括非常详细的许可模型,您可以将其映射到每个git repo中的特定路径; 一个由Lucene支持的搜索功能,一个复制引擎,以便可以将本地git repo的更改推到其他任何地方; 它本身是用于git存储库及其命令行和GUI界面的功能强大的http和ssh服务器,通常具有全方位的工业风格功能。
Where Gerrit is falling short is that on the “self-install” side, it is definitely a little obtuse and unforgiving about things. It was not that easy to set up, and you’ll likely have to spend a lot of time reading stack traces in the logs to figure out various issues – documentation, links to packages, and other online help is a little scattered and sometimes incomplete, especially for the plugins. It’s not very user friendly on the adminstration side yet. But hosting it yourself is still the way to go, so that when you hit a view like “all”, you see just your projects and not a huge list of other people’s projects.
Gerrit不足之处在于,在“自安装”方面,这肯定有点晦涩难懂。 设置起来并不那么容易,您可能不得不花费大量时间阅读日志中的堆栈跟踪信息以找出各种问题-文档,软件包链接以及其他在线帮助有些分散,有时不完整,尤其是对于插件。 在管理方面还不是很用户友好。 但是,仍然要自己托管它,因此,当您看到“全部”之类的视图时,您只会看到自己的项目,而看不到其他人的项目的巨大清单。
The move to self-hosting services again is kind of a pendulum swing for me; a couple of years ago I was entirely gleeful to move my issue tracking off of Trac and onto Bitbucket, but i think the reason for that was mostly due to Trac’s inability to limit spam accounts as well as a burdensome performance model and very little upstream development. With Gerrit, I’m self-hosting again, however all authorization is pushed up to Github with OAuth, so that I’m not dealing with fake user accounts and so far not any spammers either.
再次转向自助服务对我来说是一种钟摆。 几年前,我完全乐于将问题从Trac转移到Bitbucket,但我认为其原因主要是由于Trac无法限制垃圾邮件帐户,繁重的性能模型和很少的上游开发。 使用Gerrit,我可以再次自我托管,但是所有授权都会通过OAuth推送到Github,这样我就不会处理虚假的用户帐户,到目前为止,也没有垃圾邮件发送者。
I’m using the Gerrit Oauth plugin to provide Github logins, and this plugin also includes support for Google Oauth which I haven’t turned on yet, and Bitbucket OAuth which I couldn’t get working.
我正在使用Gerrit Oauth插件提供Github登录,该插件还包括对我尚未打开的Google Oauth和我无法使用的Bitbucket OAuth的支持。
For integration with community-supplied code submissions, I am still using pull requests as the primary entrypoint into the system. Github and Bitbucket require that you leave the “pull request” button on in any case, so people are naturally going to send you code on both of them no matter what you say, so we might as well use them. The pull request allows me to have a quick preview of what we’re dealing with, and I then import it into Gerrit using a semi-manual process. To achieve this consistently, I’ve created the prtogerrit script which communicates with both the Github and Bitbucket APIs to pull in any target pull request, squash it, push it into Gerrit as a new review, and add comments to the pull request referring the contributor to our Gerrit registration page. Pull requests submitted through Bitbucket still necessarily get that big ugly “DECLINED” status, however it is now consistent for all BB pull requests and the messaging is clear that the work is continued on Gerrit.
为了与社区提供的代码提交集成,我仍将拉取请求用作系统的主要入口点。 Github和Bitbucket在任何情况下都要求您保留“拉取请求”按钮,因此无论您说什么,人们自然都会向他们发送代码给他们,因此我们也可以使用它们。 拉取请求使我可以快速预览正在处理的内容,然后使用半手动过程将其导入Gerrit。 为了始终如一地实现这一目标,我创建了prtogerrit脚本,该脚本与Github和Bitbucket API进行通信,以拉入任何目标拉取请求,将其压缩 ,将其作为新的评论推入Gerrit,并在拉取请求中添加引用我们的Gerrit注册页面的贡献者。 通过Bitbucket提交的拉取请求仍然必须处于丑陋的“拒绝”状态,但是现在对于所有BB拉取请求都是一致的,并且消息传递很清楚,有关Gerrit的工作仍在继续。
Since I’ve been using Gerrit, I’ve been surprised at how much more productive I became; being able to see every code change being worked on by anyone all under one interface is very freeing, and the workflow that lets me have the entire change from implementation to tests to changelog and migration notes in one clean, mergable commit, fully run through multiple Jenkins CI jobs before it gets merged has made me totally comfortable pushing a big red “merge” button at the end, which was never the case with pull requests and other ad-hoc patchfiles and feature branches.
自从我使用Gerrit以来,我惊讶于我的生产率提高了多少。 能够看到任何人在一个界面下进行的所有代码更改都非常轻松,而工作流程使我能够通过一次干净的,可合并的提交,将从实现到测试到更改日志和迁移说明的全部更改完整地运行到多个Jenkins CI的工作在被合并之前,让我完全自如地按下了一个大的红色“合并”按钮,而对于拉取请求以及其他临时补丁文件和功能分支却从来没有这样。
翻译自: https://www.pybloggers.com/2016/04/gerrit-is-awesome/
杰里6916