Powerful GitHub Action for automatically committing and pushing changes back to your repository.
- Docker Hub: devopsinfra/action-commit-push:latest
- GitHub Packages: ghcr.io/devops-infra/action-commit-push:latest
- ๐ Custom commit messages: Add custom prefixes and messages to commits
- ๐ Commit signing: Sign generated commits with GPG or SSH keys
- ๐ฟ Branch management: Create new branches automatically with optional timestamps
- โฐ Timestamp support: Add timestamps to branch names for cron-based updates
- ๐ Integration-ready: Works seamlessly with other DevOps workflows
- ๐ช Force push options: Support for
--forceand--force-with-leasewhen needed - ๐ Pull request integration: Perfect companion for automated PR workflows
- ๐ฏ Deterministic branch reset: Optionally reset target branches to a chosen base branch before committing
- ๐งฉ Empty commit support: Optionally create empty commits for no-diff automation flows
- ๐ก๏ธ Rebase conflict control: Choose strict failure or legacy best-effort behavior on rebase conflicts
Perfect for automation workflows and integrates seamlessly with devops-infra/action-pull-request.
This action supports three tag levels for flexible versioning:
vX: latest patch of the major version (e.g.,v1).vX.Y: latest patch of the minor version (e.g.,v1.2).vX.Y.Z: fixed to a specific release (e.g.,v1.2.3).
- name: Run the Action uses: devops-infra/[email protected] with: github_token: "${{ secrets.GITHUB_TOKEN }}" add_timestamp: true amend: false commit_prefix: "[AUTO]" commit_message: "Automatic commit" user_name: "" user_email: "" signing_mode: "" signing_key: "" signing_passphrase: "" force: false force_with_lease: false no_edit: false organization_domain: github.com target_branch: update/version
| Input Variable | Required | Default | Description |
|---|---|---|---|
github_token |
Yes | "" |
Personal Access Token for GitHub for pushing the code. |
add_timestamp |
No | false |
Whether to add the timestamp to a new branch name. Uses format %Y-%m-%dT%H-%M-%SZ. |
amend |
No | false |
Whether to make an amendment to the previous commit (--amend). Can be combined with commit_message to change the commit message. |
commit_prefix |
No | "" |
Prefix added to commit message. Combines with commit_message. |
commit_message |
No | "" |
Commit message to set. Combines with commit_prefix. Can be used with amend to change the commit message. |
user_name |
No | "" |
Git user.name used for created commits. Defaults to ${{ github.actor }} when empty. |
user_email |
No | "" |
Git user.email used for created commits. Defaults to ${{ github.actor }}@users.noreply.<organization_domain> when empty. |
signing_mode |
No | "" |
Commit signing mode. Supported values are gpg and ssh. Leave empty to disable signing. |
signing_key |
No | "" |
Signing key material. For gpg, provide an ASCII-armored private key export. For ssh, provide a private key in OpenSSH or PEM format. |
signing_passphrase |
No | "" |
Optional passphrase for the signing key. Passphrase-protected GPG keys are supported. Encrypted SSH signing keys are rejected in the current runtime. |
force |
No | false |
Whether to use force push (--force). Use only when you need to overwrite remote changes. Potentially dangerous. |
force_with_lease |
No | false |
Whether to use force push with lease (--force-with-lease). Safer than force as it checks for remote changes. Set fetch-depth: 0 for actions/checkout. |
base_branch |
No | "" |
Base branch used to sync or reset target_branch. When empty, the action auto-detects main/master or origin HEAD. |
reset_target_branch |
No | false |
Whether to hard-reset target_branch to origin/base_branch before committing. Recommended for deterministic release branches. |
allow_empty_commit |
No | false |
Whether to create an empty commit when there are no file changes. Useful for workflows that must open a PR with no file diff. |
fail_on_rebase_conflict |
No | true |
Whether to fail the action if rebase onto base_branch conflicts. Set to false to keep legacy best-effort rebase behavior. |
no_edit |
No | false |
Whether to not edit commit message when using amend (--no-edit). |
organization_domain |
No | github.com |
GitHub Enterprise domain name. |
target_branch |
No | current branch | Name of a new branch to push the code into. Creates branch if not existing unless there are no changes and amend is false. |
repository_path |
No | . |
Relative path under ${{ github.workspace }} where the repository is checked out. Set this when actions/checkout uses path:. |
| Output | Description |
|---|---|
files_changed |
List of changed files, as returned by git diff --staged --name-status. |
branch_name |
Name of the branch code was pushed into. |
Commit and push changes to the currently checked out branch.
name: Run the Action on: push jobs: change-and-push: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - name: Change something run: | find . -type f -name "*.md" -print0 | xargs -0 sed -i "s/foo/bar/g" - name: Commit and push changes uses: devops-infra/[email protected] with: github_token: ${{ secrets.GITHUB_TOKEN }} commit_message: "Replace foo with bar"
Commit and push changes to a new branch and create a pull request using devops-infra/action-pull-request.
name: Push changes and create PR on: push jobs: change-and-push: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - name: Change something run: | find . -type f -name "*.md" -print0 | xargs -0 sed -i "s/foo/bar/g" - name: Commit and push changes uses: devops-infra/[email protected] with: github_token: ${{ secrets.GITHUB_TOKEN }} commit_prefix: "[AUTO-COMMIT] " commit_message: "Replace foo with bar" - name: Create pull request uses: devops-infra/action-pull-request@v1 with: github_token: ${{ secrets.GITHUB_TOKEN }} body: "**Automated pull request**<br><br>Replaced foo with bar" title: ${{ github.event.commits[0].message }}
When you need to amend the previous commit and force push (useful when adding automatic changes to manual commit).
name: Amend and force push on: workflow_dispatch: inputs: new_commit_message: description: 'New commit message' required: true default: 'Updated commit message' jobs: amend-commit: runs-on: ubuntu-latest steps: - name: Checkout repository with full history uses: actions/checkout@v6 with: fetch-depth: 0 # Required for force_with_lease - name: Make some changes run: | echo "Additional content" >> README.md - name: Amend and force push with lease uses: devops-infra/[email protected] with: github_token: ${{ secrets.GITHUB_TOKEN }} commit_message: ${{ github.event.inputs.new_commit_message }} amend: true force_with_lease: true # Safer force push option
Commit and push when actions/checkout uses a custom path.
name: Commit from custom checkout path on: push jobs: change-and-push: runs-on: ubuntu-latest steps: - name: Checkout repository into custom path uses: actions/checkout@v6 with: path: work/repo - name: Change something in checked out repository run: | echo "Updated" >> work/repo/README.md - name: Commit and push changes uses: devops-infra/[email protected] with: github_token: ${{ secrets.GITHUB_TOKEN }} repository_path: work/repo commit_message: "Update README"
Override the git author/committer identity used by the action.
- name: Commit and push with custom identity uses: devops-infra/[email protected] with: github_token: ${{ secrets.GITHUB_TOKEN }} commit_message: "test(commit-push): custom identity" user_name: "Release Automation" user_email: "[email protected]"
When user_name and user_email are empty, the action defaults to:
user.name = ${{ github.actor }}user.email = ${{ github.actor }}@users.noreply.<organization_domain>
This action can sign generated commits by configuring repository-local git signing settings at runtime.
signing_mode: gpgimports an ASCII-armored private OpenPGP key into an isolated temporaryGNUPGHOME.signing_mode: sshuses an SSH private key file and git's SSH signing mode.- Temporary key material is written outside the repository and removed when the container exits.
- Passphrase-protected GPG keys are supported through non-interactive loopback pinentry.
- Encrypted SSH signing keys are currently rejected explicitly instead of falling back to interactive prompts.
- name: Commit and push signed changes uses: devops-infra/[email protected] with: github_token: ${{ secrets.GITHUB_TOKEN }} commit_message: "test(commit-push): signed with gpg" signing_mode: gpg signing_key: ${{ secrets.GPG_PRIVATE_KEY }} signing_passphrase: ${{ secrets.GPG_PASSPHRASE }}
- name: Commit and push SSH-signed changes uses: devops-infra/[email protected] with: github_token: ${{ secrets.GITHUB_TOKEN }} commit_message: "test(commit-push): signed with ssh" signing_mode: ssh signing_key: ${{ secrets.SSH_SIGNING_KEY }}
Failed to import GPG signing keyusually means the secret is not an ASCII-armored private key export.Failed to read SSH signing keyusually means the secret is not a valid private key.Encrypted SSH signing keys are not supported in this runtimemeans the key must be provided without a passphrase.- If downstream verification fails, confirm your verifier trusts the matching public key and uses git's corresponding
gpg.format.
When using amend: true, you have several options for handling the commit message:
-
Change the commit message: Set
commit_messageto provide a new message- uses: devops-infra/[email protected] with: github_token: ${{ secrets.GITHUB_TOKEN }} commit_message: "Fixed typo in documentation" amend: true force_with_lease: true
-
Keep existing message: Set
no_edit: trueto keep the original commit message- uses: devops-infra/[email protected] with: github_token: ${{ secrets.GITHUB_TOKEN }} amend: true no_edit: true force_with_lease: true
-
Default behavior: If neither is set, uses "Files changed:" with file list (when files are modified)
๐ก Note: Amending works even without file changes - useful for just changing commit messages!
This action provides two force push options for different scenarios:
- Uses
git push --force-with-lease - Safer option that checks if someone else has pushed changes to the remote branch
- Prevents accidentally overwriting other people's work
- Required: Set
fetch-depth: 0in youractions/checkoutstep - Use case: Amending commits, rebasing, or other history modifications
- Uses
git push --force - Potentially dangerous as it will overwrite remote changes unconditionally
- No safety checks - will overwrite any remote changes
- Use case: Only when you're absolutely certain you want to overwrite remote changes
force_with_lease takes precedence if both are set to true.
Pick the tag level based on your stability needs:
vX.Y.Z: exact immutable release (most predictable)vX.Y: latest patch within one minor linevX: latest patch within one major line
name: Run the Action on: push: branches-ignore: master jobs: action-commit-push: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: devops-infra/[email protected] id: Pin patch version - uses: devops-infra/[email protected] id: Pin minor version - uses: devops-infra/action-commit-push@v1 id: Pin major version
Contributions are welcome! See CONTRIBUTING. This project is licensed under the MIT License - see the LICENSE file for details.
This project is licensed under the MIT License - see the LICENSE file for details.
If you have any questions or need help, please:
- ๐ Create an issue
- ๐ Star this repository if you find it useful!
Use the manual workflow .github/workflows/manual-e2e-validate.yml to validate this action against the centralized E2E repository.
mode=refvalidates ref-oriented E2E paths against stable pinned action refs.mode=imageis wired but currently placeholder-only in the central E2E workflow for this action.
CI/CD automation also runs these E2E checks automatically:
- Pull requests: E2E validation runs through reusable org workflows.
- Release branch prepare: E2E validation runs against release candidate refs.
- Release create: E2E validation runs against production release refs.
Example trigger inputs:
mode=ref
mode=image
image_tag=v1.2.3-test
To publish images from a fork, set these variables so Task uses your registry identities:
DOCKER_USERNAME, DOCKER_ORG_NAME, GITHUB_USERNAME, GITHUB_ORG_NAME.
Two supported options (environment variables take precedence over .env):
# .env (local only, not committed)
DOCKER_USERNAME=your-dockerhub-user
DOCKER_ORG_NAME=your-dockerhub-org
GITHUB_USERNAME=your-github-user
GITHUB_ORG_NAME=your-github-org# Shell override
DOCKER_USERNAME=your-dockerhub-user \
DOCKER_ORG_NAME=your-dockerhub-org \
GITHUB_USERNAME=your-github-user \
GITHUB_ORG_NAME=your-github-org \
task docker:buildRecommended setup:
- Local development: use a
.envfile. - GitHub Actions: set repo variables for the four values above, and secrets for
DOCKER_TOKENandGITHUB_TOKEN.
Publish images without a release:
- Run the
(Manual) Release Createworkflow withbuild_only: trueto build and push images without tagging a release.