TIM PETTERSEN • SENIOR DEVELOPER • ATLASSIAN • @KANNONBOY
Code review
vs
Pull requests
@kannonboy
Code review at Atlassian
2006
2007
Atlassian acquires
Cenqua, starts using
Crucible @kannonboy
@kannonboy
2006
2007
Atlassian acquires
Cenqua, starts using
Crucible
Atlassian acquires @kannonboy
@kannonboy
2007 Cenqua, starts using
Crucible
2010 Atlassian acquires
Bitbucket
2011 Work starts on “Caviar”
! @kannonboy
@kannonboy
2010 Atlassian acquires
Bitbucket
2011 Work starts on “Caviar”
2012 Stash 1.0 ships
!
@kannonboy
@kannonboy
2011 Work starts on “Caviar”
2012 Stash 1.0 ships
!
Stash 2.0 ships with
pull requests
Unread status
@kannonboy
@kannonboy
2012 Stash 1.0 ships
Stash 2.0 ships with
pull requests
Merge checks
Comment drift
Unread status
Conflict markers
Build status integration @kannonboy
@kannonboy
Stash renamed to
Bitbucket Server2015
Merge checks
Conflict markers
Build status integration
Reviewer suggestions
Branch permissions
Comment likes
Enhanced branch permissions
Iterative review
Merge strategies
Reviewer statuses @kannonboy
@kannonboy
Bitbucket Server2015
Comment likes
Enhanced branch permissions
Iterative review
Merge strategies
Reviewer statuses
Today
@kannonboy
@kannonboy
TYPES OF REVIEW
YOU NEED CODE REVIEW
CODE REVIEW @ ATLASSIAN
TIPS FOR TEAMS
Agenda
Automated tests
@kannonboy
Automated tests
@kannonboy
human judgement needed
?
“what-evs”
bad API decision
O(n!) algorithm
technical debt
Automated tests
@kannonboy
Code
Review
Photo: Yogi (Flickr)
@kannonboy
Better
Code
Shared
Knowledge
Team
Ownership
@kannonboy
G =
1
R+1
Developer guilt
@kannonboy
Team
Ownership
@kannonboy
Team
Ownership
@kannonboy
Better
Code
Shared
Knowledge
Team
Ownership
@kannonboy
Code reviews take
negative time
@kannonboy
Reviews and releases
10
20
30
40
Daily Weekly Monthly Quarterly Yearly
Code Review No Code Review
Source: Atlassian Git Survey 2013
@kannonboy
Types of code review
@kannonboy
Pull requests
Code review
Post-commit review
Pre-commit review
master
for/master
Staging area @kannonboy
Pre-commit review
master
@kannonboy
Pre-commit review
dev $project-dev@example.com
master
maintainer @kannonboy
// flat fees and taxes
final float customsFee = 5.5f;
final float immigrationFee = 7f;
final float federalTransportTax = .025f;
public float calculateAirfare(float baseFare) {
float fare = baseFare;
fare += immigrationFee + customsFee;
fare *=
return fare;
}
AirfareCalculator.java
federalTransportTax;
@kannonboy
// flat fees and taxes
final float customsFee = 5.5f;
final float immigrationFee = 7f;
final float federalTransportTax = .025f;
public float calculateAirfare(float baseFare) {
float fare = baseFare;
fare += immigrationFee + customsFee;
fare *=
return fare;
}
(1 + )
AirfareCalculator.java
federalTransportTax ;
@kannonboy
Pre-commit review
From: Tim Pettersen <tim@atlassian.com>
Date: Mon, 12 Sep 2016 10:24:10 +1000
Subject: [PATCH] Calculate federal transport tax correctly
--- a/com/atlassian/airfare/AirfareCalculator.java
+++ b/com/atlassian/airfare/AirfareCalculator.java
@@ -10,7 +10,7 @@
public float calculateAirfare(float baseFare) {
float fare = baseFare;
fare += immigrationFee + customsFee;
- fare *= federalTransportTax;
+ fare *= (1 + federalTransportTax);
return fare;
}
$ git format-patch HEAD~1 --stdout
@kannonboy
Pre-commit review
dev
maintainer
public float calculateAirfare(float baseFare) {
float fare = baseFare;
fare += immigrationFee + customsFee;
- fare *= federalTransportTax;
+ fare *= (1 + federalTransportTax);
return fare;
}
Subject: [PATCH] Calculate federal transport tax correctly
@kannonboy
>
>
>
>
>
The braces are unnecessary.
Pre-commit review
dev
maintainer
public float calculateAirfare(float baseFare) {
float fare = baseFare;
fare += immigrationFee + customsFee;
- fare *= federalTransportTax;
+ fare *= (1 + federalTransportTax);
return fare;
}
Subject: Re: [PATCH] Calculate federal transport tax correctly
>
>
@kannonboy
>
>
>
>
>
>
>
> >
>
Technically true, but I think they add clarity.
>
>
>
>
>
>
>
The braces are unnecessary.
Pre-commit review
dev
maintainer
public float calculateAirfare(float baseFare) {
float fare = baseFare;
fare += immigrationFee + customsFee;
- fare *= federalTransportTax;
+ fare *= (1 + federalTransportTax);
return fare;
}
Subject: Re: Re: [PATCH] Calculate federal transport tax correctly
@kannonboy
> > > > > > > > > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > > > > > > > >
Pre-commit review
dev
maintainer
Subject: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re:
@kannonboy
Iteration
m
aster
@kannonboy
Pre-commit review
Linus Torvalds*
Module
maintainers
File / driver
maintainers
Contributors
linux-kernel@vger.kernel.org
* Gross oversimplification,
check out: bit.ly/linux-dev
@kannonboy
Pre-commit review
Junio C Hamano*
Contributors
git@vger.kernel.org
* Also an oversimplification
@kannonboy
Pull requests
Post-commit review
Pre-commit review
master
for/master
Staging area
Pre-commit review
Version control agnostic
Difficult to read
High barrier to submit patches
Simple and decentralized
Difficult to iterate
Easy to keep ‘000s of people in the loop
Have to manually merge work
@kannonboy
Post-commit review
@kannonboy
Flexible structure
master
master
patches & untracked files
commits
branches
specific filesmultiple repos
@kannonboy
Iterative review
Branch
diff
Merge
diff
Pull request diffs
@kannonboy
Iterative review
Branch
diff
Post-commit review diffs
Arbitrary commit diffs
@kannonboy
Iterative review in
@kannonboy
Iterative review in
@kannonboy
Not an SCM
SCM host
(e.g. Bitbucket)
Review host
(e.g. Crucible)
Dev team
push & pull
code review
slurp
slurp
slurp
slurp
@kannonboy
Post-commit review
Post-commit review
Supports popular CVCS and DVCS
Have to manually merge work
Flexible review content
Need a separate VCS host
Easy to iterate
Hard to enforce process
@kannonboy
Pull requests
master
for/master
Staging area @kannonboy
Gerrit
and DIFFY
The Kung Foo
Review Cuckoo
@kannonboy
Gerrit is very “Git-y”
$ git config -f ~/gerrit/etc/gerrit.config gerrit.canonicalWebUrl
http://localhost:8080/
@kannonboy
Staging area review
for/master
master
reviewers approved?
verified (build passing)?
Dev team
fetch
push
@kannonboy
From: Gerrit Code Review - A Quick Introduction
@kannonboy
From: Gerrit Code Review - A Quick Introduction
+2
+1
0
-1
-2
@kannonboy
“squash commits first”
$ git push origin HEAD:refs/for/master
# typey type type
$ git commit -am “Review feedback”
Counting objects: 2108776, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (59/59), done.
Writing objects: 100% (86/86), 893.21 KiB, done.
Total 86 (delta 0), reused 0 (delta 0)
! [remote rejected] HEAD -> refs/for/master (squash commits first)
error: failed to push some refs to ‘ssh://...'
@kannonboy
“squash commits first”
for/master
@kannonboy
“squash commits first”
for/master
push
@kannonboy
“squash commits first”
for/master
push
push --force
@kannonboy
“squash commits first”
for/master
push
push --force
push --force
@kannonboy
From: Gerrit Code Review - A Quick Introduction
@kannonboy
Pull requests
Post-commit review
Pre-commit review
master
for/master
Staging area
Staging area review
Sophisticated policy enforcement
Steep learning curve to use & administer
Iteration is a little awkward
FOSS project built in Java, on JGit
Git only
Clean commit history
@kannonboy
Pull requests
it review
@kannonboy
Branches only
master
master
patches & untracked files
commits
branches
specific filesmultiple repos
@kannonboy
Pull requests
review before merging
> Code review
@kannonboy
Pull requests > Code review
Passing build
Reviewer sign-off
Ready for deployment
@kannonboy
Pull requests > Code review
Passing build
Reviewer sign-off
Ready for deployment
@kannonboy
Two developers about to
press the “Merge” button
@kannonboy
Merge Strategies
@kannonboy
@kannonboy
--no-ff
--ff-only
--squash --ff-only
--squash
--ff
@kannonboy
git merge --no-ff
@kannonboy
m
aster
feature/JIRA-123
“Always create a merge commit.”
git merge --no-ff
@kannonboy
m
asterfeature/JIRA-123
“Always create a merge commit.”
git merge --ff
@kannonboy
m
aster
feature/JIRA-123
“Fast forward if you can, otherwise
create a merge commit.”
git merge --ff
@kannonboy
m
aster
feature/JIRA-123
“Fast forward if you can, otherwise
create a merge commit.”
git merge --ff
@kannonboy
m
aster
“Fast forward if you can, otherwise
create a merge commit.”
git merge --ff
@kannonboy
m
aster
“Fast forward if you can, otherwise
create a merge commit.”
git merge --ff-only
@kannonboy
m
aster
feature/JIRA-123
“Only allow fast forwards.”
git merge --ff-only
@kannonboy
m
aster
feature/JIRA-123
“Only allow fast forwards.”
git merge --ff-only
@kannonboy
m
aster
“Only allow fast forwards.”
git merge --ff-only
@kannonboy
m
aster
“Only allow fast forwards.”
git merge --ff-only
@kannonboy
m
aster
“Only allow fast forwards.”
git merge --ff-only
@kannonboy
m
aster
“Only allow fast forwards.”
git merge --squash
@kannonboy
“Combine commits on branch into a new commit
on master.”
m
aster
feature/JIRA-123
git merge --squash
@kannonboy
“Combine commits on branch into a new commit
on master.”
m
aster
git merge --squash 
@kannonboy
“Combine commits on branch into a new commit on master.
Fail if master has any commits that branch doesn’t.”
m
aster
--ff-only
git merge --squash 
@kannonboy
“Combine commits on branch into a new commit on master.
Fail if master has any commits that branch doesn’t.”
m
aster
--ff-only
git merge --squash 
@kannonboy
“Combine commits on branch into a new commit on master.
Fail if master has any commits that branch doesn’t.”
m
aster
--ff-only
Merge Commit Fast forward Squash
Concise history
Lose context of how
features evolved
Which should I use?
“Ugly” history
Full traceability
Hard to screw up
mostly some
--no-ff --ff-only --squash
@kannonboy
No merge commits
Verbose history
Requires rebasing
Pull requests
bit.ly/git-lfs
Sophisticated policy enforcement
Less flexible review content
DVCS had some limitations around file size
Choice of merge strategies
Multiple team members can author code under review
Git & Mercurial
@kannonboy
pull requests
@kannonboy
Tim’s
tips for
top ten
1. One issue, one pull request
= 
@kannonboy
1. One issue, one pull request
# what’s shipping?
$ git branch --merged
# what’s left to ship?
$ git branch --no-merged
@kannonboy
master
IN REVIEW DONEIN PROGRESSOPEN
@kannonboy
Automatic Transitions
feature/JIRA-30
master
IN REVIEW DONEIN PROGRESSOPEN
Branch created!
@kannonboy
Automatic Transitions
feature/JIRA-30
master
IN REVIEW DONEIN PROGRESSOPEN
Pull Request Created!
@kannonboy
Automatic Transitions
feature/JIRA-30
master
IN REVIEW DONEIN PROGRESSOPEN
Pull Request Merged!
@kannonboy
Automatic Transitions
2. Minimum TWO approvals before merge
@kannonboy
2. Minimum TWO approvals before merge
3. Have 1.5x - 2.5x that number reviewers
@kannonboy
Fewer reviewers find more defects
0
7.5
15
22.5
30
1 2 3 4 5 6 7 8 9
Defects/kLoC
Number of Reviewers
@kannonboy
source: bit.ly/review-stats
More reviewers spend less time
0
7
14
21
28
1 2 3 4 5 6
Minutesspent/reviewer
Number of Reviewers
@kannonboy
source: bit.ly/review-stats
4. Use blame to pick reviewers
@kannonboy
4. Use blame to pick reviewers
$ npm install -g git-guilt
# find blame delta for current branch
$ git guilt `git merge-base master HEAD` HEAD
Alice Foo ++++++++++++++++++++++++(239)
Bob Bar ++++++++
Eve Baz -------
Mira Ted ----------------
Bec Opal ------------------------(-159)
@kannonboy
4. Use blame to pick reviewers
bit.ly/suggest-reviewers @kannonboy
4. Use blame to pick reviewers
bit.ly/suggest-reviewers @kannonboy
4. Use blame to pick reviewers
bit.ly/suggest-reviewers @kannonboy
5. @mention specialists
@kannonboy
6. Stuck in review?
Make Tuesday & Thursday inbox zero days
@kannonboy
betterCode;
7. Move comments into code
review
comments
// comments
// in code
@kannonboy
8. Build a team policy, as a team…
…and enforce it! @kannonboy
9. Add screenshots for UI/UX changes
(gifs / videos are even better) @kannonboy
9. Add screenshots for UI/UX changes
(gifs / videos are even better) @kannonboy
Monosnap GIPHY ScreenFlow
@kannonboy
Ask a programmer to review 10
lines of code, they'll find 10 issues.
Ask them to do 500 lines and
they'll say it looks good.
@GIRAYOZIL
“
”
10. Keep it concise
10. Keep it conciseSecondsperline
Lines of Code
1 line per second
100 lines per second
@kannonboy
source: bit.ly/review-stats
Code Review vs. Pull requests
Need to review multiple
repos at once
Not on Git
Heavily iterative workflow
Literally everyone else
Dendrophobia
+
@kannonboy
(Traditional)
@kannonboy
bitbucket.org
Bitbucket
atlassian.com/crucible
Crucible
gerritcodereview.com
Gerrit
Looking
for
more?
Follow me for occasional Git &
Bitbucket trivia

Code reviews vs Pull requests