Conversation
This patch is an internal-only change to swap from using the GraphQL API to using the REST API, which will unlock future changes due to the REST API being more powerful.
Specifying which commits to push started to become untenable. In an effort to simplify, push now no longer takes any non-flag arguments. Instead, it will always push local commits that do not exist on the remote. Note that `--head-sha` is still recommended to be used as a safety check to ensure the remote has not moved from where you expected. If the remote HEAD is not an ancestor of the local HEAD, the push will fail due to diverged history.
Similar to the push command simplification, the commit command had some bad UX. The original intent was to allow folks to use `commit-headless commit` when they didn't even have the repository itself checked out, but in practice that hasn't been seen (consider that your changes tend to be in CI jobs where the code is available). Instead of requiring users to supply the list of changed files, the `commit` command now operates like `git commit && git push` and takes whatever changes have been staged.
Previously, commit-headless would just print all log information to
stderr and save stdout purely for the final pushed ref. It was generally
fine, but we can improve it.
Now, commit-headless detects when it's running in an Action context and
prints out messages to standard output using proper log group workflow
commands while leaving non-Action usage alone.
Example:
▶ Pushing to owner/repo (branch: main) [collapsible]
Commits: abc123, def456
Remote head commit: 111222
▶ Commit abc12345: Update README [collapsible]
Author: A U Thor <a@b.com>
Changed files: 1
- MODIFY: README.md
ℹ️ Pushed 1 commit(s) to https://github.com/owner/repo/commits/main
This patch adds commit-headless replay, useful for situations where you want to replace a series of existing remote commits with signed equivalents. See README.md or `commit-headless reply --help` for more.
Some callers need to be able to force push. If they have a complex workflow that involves local rebasing, for instance, they should be able to force push. To force push (or commit), you must specify `--head-sha` and `--force`. If set, the remote HEAD check is skipped and instead `--head-sha` is used as the parent for the first created commit (or only commit in the case of the commit command). refs #45
6918b50 to
6f5e553
Compare
Sometimes commits made by the API are not signed. We've seen this intermittently internally. Instead of allowing unsigned commits to be created, we're now verifying created commits. If a created commit is unsigned, commit-headless will make up to `--sign-attempts` attempts (default 5) with exponential backoff before hard failing. While this will technically create up to 5 new commits on the remote, the actual branch reference is only updated once the signed commit is created. The dangling commits will be removed by GitHub during normal garbage collection. As part of this, we only update the branch pointer after *all* commits are created, not when *each* commit is created. This means a failure in the middle of a push of 5 commits will not leave you with a subset of remote commits.
77a93f5 to
ec9e2b3
Compare
drewcsillagdd
approved these changes
Mar 24, 2026
github-actions Bot
added a commit
that referenced
this pull request
Mar 26, 2026
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
commit-headless v3.0.0
This PR contains breaking changes to the CLI and action interfaces, along with new features.
Breaking Changes
push command
The push command no longer accepts commit arguments. It now automatically determines which local commits need to be pushed by comparing local HEAD with the remote branch HEAD.
Before:
After:
The
commitsaction input has been removed.commit command
The commit command no longer accepts file arguments. It now reads from the git staging area, similar to
git commit.Before:
After:
The
filesaction input has been removed.New Features
--forcefor commit and push commandsWhen
--forceis set,--head-shais used directly as the parent of the first pushed commit, bypassing the remote HEAD safety check. The branch ref is force-updated even if the push is not a fast-forward. This is useful for, e.g., pushing rebased commits.Without this, there is no way for commit-headless to force push.
replay command
New command to replay existing remote commits as signed commits. Useful when an action or bot creates unsigned commits that you want to replace with signed versions.
The command fetches the remote branch, extracts commits since the specified base, recreates them as signed commits, and force-updates the branch ref.
Action usage:
File mode preservation
File modes (such as the executable bit) are now preserved when pushing commits. Previously all files were created with mode 100644.
GitHub Actions logging
When running in GitHub Actions, output now uses workflow commands:
Internal Changes