Clear mapping of change request == commit, allowing for easy building of multiple in flight change requests, rearranging them by using git rebase, updating with push to refs/for/master. Easy diffing between states of the CR (patch sets), so you can see what changes since the last round of comments, even if it spanned multiple updates. This is the feature I miss the most from other code review systems - be able to easily work on another commit that bases on one that I just sent out for review (even starting review on the new while the parent still hasn't finished being reviewed!), and rebasing my current change as the parent change gets reviewed/updated.
Possibility to send out a PR for review using just a push (change message in commit, push to refs/for/master%r=foo).
Snappy and compact code review experience (no space wasted for whitespace, avatars, pretty buttons). Full coverage with keyboard shortcuts.
Powerful review rule system based in Prolog, allowing for things like code owners, experimental subdirectories without the need for review, etc.
was forced to use Gerrit by a client. I could never get the hang of this, I like to do frequent commits on short lived branches and using vanilla git. I never wanted any more features other than a nice UI to encourage people to review.
The nice UI for review works well exactly because it limits the functionality available to users and enforces a particular commit model. If you don't do that, you get the code review mess that are Github/GitLab PRs/MRs - difficult to tell apart how commits relate to the change and how it progresses through review, because the entire branch history is free-form.
It's possible to allow users to have multiple commits but still show review between the submitted "tip" commits. If you want you don't even need to show the other commits in the UI.
One thing one has to get away from that one change request == one issue. Multiple small commits as separate change requests for one story are fine as long as they work standalone (which is generally a good idea, e.g. to enable bisecting)
I much prefer the model of force-pushing your development branch to create change sets. It lets you more easily see how development evolves in response to feedback. And the final state of the branch which gets merged leaves all the in-progress work that no one cares about behind only in Gerrit.
With Github/lab's model, if you force push your PR, you lose the ability to view its previous state and diff against that. Alternately, if you just keep adding commits, then the final branch that gets merged (unless you squash) has all the in-progress work which pollutes the repo's history.
Gerrit also has a finer grained permission model, but I don't care as much about that.
Gerrit definitely expects the user to understand how git works conceptually a bit more than Github/lab.
Yup, GitLab works as expected here. It's always surprised me how quickly the old commit is garbage-collrcted when you force-push a branch on GitHub. It causes weird errors in CI runs and breaks viewing the old commits.
Seriously I'll pay for those couple of KiB of space, just keep it around. (at least until the PR is closed)
> With Github/lab's model, if you force push your PR, you lose the ability to view its previous state and diff against that.
I'm not sure about Gitlab, but Github has recently added a feature where you can view the diff between the old branch head and new one. But, as far as I'm aware, there's no way to check out the previous branch head from the repo due to a lack of a remote branch pointing to it.
At least git itself provides a range-diff command that allows you do see a diff between the commits between two versions of a given branch.
Yes, I very much agree: the rebase-based workflow is what makes Gerrit superior to all other systems I've tried (of which I find Github and Bitbucket particularly loathsome).
I felt I needed to correct you because with Gerrit you reserve the concept of force pushing for exceptional cases, which I think is the correct mental model. Force pushing should not be done frivolously.
I would say it's quite different, since you don't overwrite anything. Old patch sets are still available should you wish to roll back/reference either a particular commit, or a whole chain of commits.
It's not a force push under the hood. Under the hood a new branch is created (first patch set is /refs/changes/nnnn/0, second is /refs/changes/nnnn/1, etc.). From the end user perspective the result is quite plausibly similar to force push.
The branch model must have changed. I used to push directly to a branch that was the change number (not the revision number) and of course had to force because it was the same.
So what happens when you push to changes/nnnn/12 when revision 11 hasn’t been created?
At least the way our installation works we don't push to changes/nnnn/12, rather changes are pushed to refs/for/{branch} (often refs/for/master). This endpoint isn't an actual branch. It triggers gerrit to look up the nnnn for the Change-Id in the commit message and create the appropriate branch for the next patch set.