Home / Alt manpages / gh-search-commits(1)

  • gh-search-commits(1)
  • User command
  • linux

Search GitHub Commits Precisely with gh search commits

You will search GitHub commit history from a Linux shell, narrow the result with repository and identity filters, and request machine-readable fields when a script needs them. Allow about ten minutes for a first search, assuming gh is installed and authenticated for the GitHub account you intend to use.

1. Check the installed command

This guide follows the installed gh-search-commits(1) manual. The command here is GitHub CLI 2.87.3, while the Ubuntu package metadata on this machine reports gh 2.45.0-1ubuntu0.3+esm3. That difference reflects the executable currently found on PATH, so check your own system before relying on version-specific output or scripting around formatting.

$ command -v gh
/usr/bin/gh
$ gh --version
gh version 2.87.3 (2026-02-23)
$ gh search commits --help

The help output should show the usage form gh search commits [<query>] [flags]. If the executable is missing, install GitHub CLI through your normal distribution or vendor process. Do not add sudo to searches: reading public search results does not require elevated privileges.

Words after the subcommand form the query. This example looks for commits matching both words:

$ gh search commits readme typo
Showing 30 of 30 commits
... result rows printed here ...

The exact repositories, authors and row formatting depend on GitHub's current index and your account access. The default limit is 30 commits. A phrase must be quoted so the shell passes it as one argument:

$ gh search commits "bug fix"

A query is not a local grep of cloned repositories. It asks GitHub's search service, so authentication, network access, API limits and repository visibility can affect the result. A successful command with no matching rows is different from an authentication or network error.

3. Narrow the repository and identity

Use --repo when the search must stay inside a named repository. Replace the placeholder with an owner and repository that you can access:

$ gh search commits "parser error" --repo OWNER/REPOSITORY --limit 20

The command also has separate filters for authors and committers. They are not interchangeable: the author records who wrote the change, while the committer records who recorded it in the repository history.

$ gh search commits --author=OCTOUSER --repo OWNER/REPOSITORY
$ gh search commits --committer=OCTOUSER --repo OWNER/REPOSITORY
$ gh search commits --author-name="Jane Doe" --repo OWNER/REPOSITORY

Use the exact identity filter that answers your question. Do not infer that a commit's author and committer are the same, especially after rebases, merges or automated imports.

4. Filter by dates, hashes and merge status

Author and committer dates are separate options. The manual accepts date expressions such as a less-than comparison; quote the value so the shell does not treat the comparison character specially:

$ gh search commits --author-date="<2026-02-01" --repo OWNER/REPOSITORY
$ gh search commits --committer-date=">=2026-01-01" --repo OWNER/REPOSITORY

For a known object, use --hash. To focus on history topology, add --merge; to search for a particular parent or tree, use --parent or --tree.

$ gh search commits --hash=COMMIT_SHA --repo OWNER/REPOSITORY
$ gh search commits --merge --repo OWNER/REPOSITORY --limit 50

These filters narrow the GitHub search request. They do not alter commits, branches or pull requests, so there is no undo operation and no persistent repository change.

5. Control ordering and the amount fetched

--limit controls the maximum number of commits fetched and defaults to 30. Start small while refining a query, then increase it deliberately. The default sort is best-match. Date ordering only applies when you choose one of the supported sort values:

$ gh search commits "release note" --repo OWNER/REPOSITORY \
    --sort=committer-date --order=desc --limit 10

The available sort values are author-date and committer-date. --order is ignored unless --sort is specified. That is an easy trap in scripts: adding --order=asc alone does not turn the default best-match search into an oldest-first search.

6. Request stable fields for a script

Human-oriented rows are useful at a terminal, but a script should request named JSON fields. The installed help lists author, commit, committer, id, parents, repository, sha and url. Pair --json with --jq when you need a small, predictable projection:

$ gh search commits "security fix" --repo OWNER/REPOSITORY \
    --limit 10 --json sha,commit,url \
    --jq '.[] | [.sha, .commit.message, .url] | @tsv'
COMMIT_SHA	commit message text	https://github.com/OWNER/REPOSITORY/commit/COMMIT_SHA

JSON field names and the jq expression are case-sensitive. Commit messages can contain tabs or newlines, so treat this display as a report rather than an unambiguous interchange format. If another tool consumes the data, keep the JSON form and parse it with that tool instead of scraping the default table.

For Go-template formatting, use --template and consult gh help formatting. Do not combine several formatting modes casually: choose the one your consumer can validate.

First repeat the command with a small limit and an explicit repository. Check that OWNER/REPOSITORY is spelled correctly and that the account can see the repository. Then separate query problems from authentication problems:

$ gh auth status
$ gh search commits --repo OWNER/REPOSITORY --limit 1
$ printf 'exit status: %s\n' "$?"
exit status: 0

The final status describes the command, not whether a row matched. Inspect the actual output before treating status 0 as a useful match. If authentication is missing, follow your organisation's approved gh auth process. Do not paste tokens into a command, shell history or an article. If a query contains a hyphen and behaves unexpectedly, read the broader gh search --help guidance about query handling before changing the search terms.

Done means

  • You confirmed which gh executable and version will run.
  • Your query uses quotes for phrases and exact repository placeholders are replaced.
  • You distinguished author, committer, author date and committer date filters.
  • You set --sort when ordering mattered, rather than relying on --order alone.
  • Scripts use --json with an explicit field list and do not scrape decorative table output.
  • You can tell an empty result from a failed request and have not changed repository state.