Draft: feat: Add cursor-based pagination to Commits API
This is a proof of concept that is going to be used as a reference in the epic gitlab-org#21573
Summary
Adds opt-in cursor-based pagination to the Commits API. This fixes broken pagination where all pages return the same commits when using all=true.
Problem
When calling /api/v4/projects/:id/repository/commits?all=true&page=N, pagination is broken - every page returns the same commits. This is because Git's --reverse flag reverses output after --skip and --max-count are applied.
Solution
Add cursor-based pagination using the existing ListCommits RPC which already works correctly:
- New
pagination=keysetparameter to opt-in to cursor pagination - New
page_token=<sha>parameter for subsequent page requests - Returns
X-NEXT-CURSORheader with SHA for next page - Existing
pageparameter unchanged (backward compatible) - Supports
all=trueby passing--allpseudo-revision to Gitaly
Usage
# First page (all commits from all branches)
GET /api/v4/projects/:id/repository/commits?pagination=keyset&all=true
# Response header: X-NEXT-CURSOR: abc123...
# Next page
GET /api/v4/projects/:id/repository/commits?pagination=keyset&all=true&page_token=abc123...Limitations
When using pagination=keyset, the following parameters are not supported and will return a 400 error:
path- File path filteringfirst_parentorder(non-default values)trailersfollowThese parameters work normally with offset pagination (withoutpagination=keyset). Closes #586997
MR acceptance checklist
- Tests added
- Documentation updated (OpenAPI spec)
- Changelog trailer included
Edited by Hunter Stewart