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=keyset parameter to opt-in to cursor pagination
  • New page_token=<sha> parameter for subsequent page requests
  • Returns X-NEXT-CURSOR header with SHA for next page
  • Existing page parameter unchanged (backward compatible)
  • Supports all=true by passing --all pseudo-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 filtering
  • first_parent
  • order (non-default values)
  • trailers
  • follow These parameters work normally with offset pagination (without pagination=keyset). Closes #586997

MR acceptance checklist

  • Tests added
  • Documentation updated (OpenAPI spec)
  • Changelog trailer included
Edited by Hunter Stewart

Merge request reports

Loading