Search code examples
gitgithubgithub-api

How to use GitHub V3 API to get commit count for a repo?


I am trying to count commits for many large github repos using the API, so I would like to avoid getting the entire list of commits (this way as an example: api.github.com/repos/jasonrudolph/keyboard/commits ) and counting them.

If I had the hash of the first (initial) commit , I could use this technique to compare the first commit to the latest and it happily reports the total_commits in between (so I'd need to add one) that way. Unfortunately, I cannot see how to elegantly get the first commit using the API.

The base repo URL does give me the created_at (this url is an example: api.github.com/repos/jasonrudolph/keyboard ), so I could get a reduced commit set by limiting the commits to be until the create date (this url is an example: api.github.com/repos/jasonrudolph/keyboard/commits?until=2013-03-30T16:01:43Z) and using the earliest one (always listed last?) or maybe the one with an empty parent (not sure about if forked projects have initial parent commits).

Any better way to get the first commit hash for a repo?

Better yet, this whole thing seems convoluted for a simple statistic, and I wonder if I'm missing something. Any better ideas for using the API to get the repo commit count?

Edit: This somewhat similar question is trying to filter by certain files (" and within them to specific files."), so has a different answer.


Solution

  • You can consider using GraphQL API v4 to perform commit count for multiple repositories at the same times using aliases. The following will fetch commit count for all branches of 3 distinct repositories (up to 100 branches per repo) :

    {
      gson: repository(owner: "google", name: "gson") {
        ...RepoFragment
      }
      martian: repository(owner: "google", name: "martian") {
        ...RepoFragment
      }
      keyboard: repository(owner: "jasonrudolph", name: "keyboard") {
        ...RepoFragment
      }
    }
    
    fragment RepoFragment on Repository {
      name
      refs(first: 100, refPrefix: "refs/heads/") {
        edges {
          node {
            name
            target {
              ... on Commit {
                id
                history(first: 0) {
                  totalCount
                }
              }
            }
          }
        }
      }
    }
    

    Try it in the explorer

    RepoFragment is a fragment which helps to avoid the duplicate query fields for each of those repo

    If you only need commit count on the default branch, it's more straightforward :

    {
      gson: repository(owner: "google", name: "gson") {
        ...RepoFragment
      }
      martian: repository(owner: "google", name: "martian") {
        ...RepoFragment
      }
      keyboard: repository(owner: "jasonrudolph", name: "keyboard") {
        ...RepoFragment
      }
    }
    
    fragment RepoFragment on Repository {
      name
      defaultBranchRef {
        name
        target {
          ... on Commit {
            id
            history(first: 0) {
              totalCount
            }
          }
        }
      }
    }
    

    Try it in the explorer