Skip to content

There does not seem to be a way to retrieve all of the actually existing commits in a repository

Summary

There does not seem to be a way to return only real commits in a repository using the commits endpoint. On the one hand, if you simply request the commits you get only the commits on the default branch. On the other hand, if you pass ´?all=true` then you get commits from all branches, including commits that have been deleted.

Steps to reproduce

Create a merge request on a repository, force push a change, and then request all of the commits back via

curl https://$gitlab_url/api/v4/projects/$project_id/repository/commits?all=true

You will find the deleted commits listed there. If you drop the ?all=true then you do not get the commits on the side branch.

Example Project

Example project: https://gitlab.com/simon.cfr/deleted_commits

What is the current bug behavior?

Consider then

$ curl "https://gitlab.com/api/v4/projects/48531827/repository/commits?all=true" | jq '.[].short_id'
"f5e7dc0e"
"600d756a"
"5a645fb2"
"0d796363"
"f229eaa2"

vs

$ curl "https://gitlab.com/api/v4/projects/48531827/repository/commits?ref_name=foo" | jq '.[].short_id'
"0d796363"
"f5e7dc0e"

Note that several of those commits do not actually exist in the repository; it is not possible to check them out.

What is the expected correct behavior?

There should be a way to request only the commits that actually exist and are possible to check out; in this case I would expect it to be

  • 0d796363
  • f5e7dc0e

Investigation (by @vyaklushin)

These commits are kept in special references: refs/merge-requests/* and refs/keep-around/*. git log --all command also picks them and returns in the response.

To solve that we can update Commit API to add a new filter option.

I tested several versions and these two options worked for me:

git log --branches --tags

or

git log --exclude="refs/merge-requests/*" --exclude="refs/keep-around/*" --all
Edited by Vasilii Iakliushin