Pull Request Review Flow Sankey Diagram: Size to Merge
See how pull requests move from size to first review outcome to merge, rework or abandonment. Replace the sample counts with your own repository data to find where review stalls.
A pull request Sankey shows what happens to changes after they are opened: approved first time, sent back for rework, or closed. Grouped by size, it shows whether large changes are what slow review down.
The example has 250 pull requests: 120 small, 90 medium and 40 large. After the first review, 130 are approved, 90 have changes requested and 30 are closed without a review. At the end 198 are merged, 12 are abandoned and 10 are still open.
The widths make the cost of size visible: 90 of the 120 small changes are approved first time, but only 5 of the 40 large ones. The rework path is one flow here, not a loop, so a request sent back twice still counts once, by its final outcome. See /sankey/ci-pipeline-outcomes for what happens to the builds those changes trigger.
How to read this diagram
- 198 of 250 pull requests (79%) end up merged; 12% are closed without review.
- 75% of small changes (90 of 120) are approved first time, against 13% of large ones (5 of 40).
- 70 of the 90 changes sent back (78%) are merged after rework; 12 are abandoned.
- 10 requests are still open, 8 of them waiting after changes were requested.
The data behind it
Invented figures for illustration. Not data about any real company, team or system.
| From | To | Amount (pull requests) |
|---|---|---|
| Small (under 100 lines) | Approved first time | 90 |
| Small (under 100 lines) | Changes requested | 22 |
| Small (under 100 lines) | Closed without review | 8 |
| Medium | Approved first time | 35 |
| Medium | Changes requested | 45 |
| Medium | Closed without review | 10 |
| Large (over 500 lines) | Approved first time | 5 |
| Large (over 500 lines) | Changes requested | 23 |
| Large (over 500 lines) | Closed without review | 12 |
| Approved first time | Merged | 128 |
| Approved first time | Still open | 2 |
| Changes requested | Merged | 70 |
| Changes requested | Abandoned | 12 |
| Changes requested | Still open | 8 |
The same data as CSV
source,target,value
Small (under 100 lines),Approved first time,90
Small (under 100 lines),Changes requested,22
Small (under 100 lines),Closed without review,8
Medium,Approved first time,35
Medium,Changes requested,45
Medium,Closed without review,10
Large (over 500 lines),Approved first time,5
Large (over 500 lines),Changes requested,23
Large (over 500 lines),Closed without review,12
Approved first time,Merged,128
Approved first time,Still open,2
Changes requested,Merged,70
Changes requested,Abandoned,12
Changes requested,Still open,8How it works
Export pull requests for one period
Include lines changed, the first review result and the final state. Take one quarter or one release.
Group by size
Choose two or three size bands and say how you cut them. Count each request once.
Count first review and final outcome
Use the first review result for the middle column and the final state for the last column.
Check the balance
Each middle node must leave as many requests as entered. Closed without review ends there.
Frequently asked questions
Why not draw review rounds as a loop?
Because widths show counts, and a loop makes the same request count twice. If rounds matter, make a second chart with the number of rounds as the middle column.
Is review speed shown?
No. The widths are counts. Put time to first review in a table next to the chart or in a separate diagram of the time bands.
Edit this pull request Sankey
Open the example as your own chart and enter your repository's counts.