A GitHub Action that safely syncs, commits, and pushes changes with automatic rebase and retry logic to handle concurrent modifications.
- Race condition handling: Automatically retries push operations when concurrent changes occur
- Rebase-first workflow: Always rebases before pushing to maintain linear history
- Safe stashing: Preserves uncommitted changes during sync operations
- Smart commit detection: Only commits when there are actual changes to push
- Configurable retry logic: Handles concurrent GitOps workflows gracefully
- Clear outputs: Returns commit status and SHA for downstream steps
- GitOps deployments: Automatically commit manifest updates and handle concurrent deployments
- Automated updates: Commit dependency updates, generated files, or version bumps
- Configuration management: Sync configuration changes across environments
- Release automation: Update version files and changelogs during releases
- uses: skyhook-io/git-sync-commit@v1
with:
commit_message: 'Update deployment manifests [skip ci]'
file_pattern: 'manifests/**/*'- name: Update kustomize manifests
uses: skyhook-io/kustomize-edit@v1
with:
overlay_dir: overlays/production
image: myapp
tag: v1.2.3
- name: Commit and push changes
uses: skyhook-io/git-sync-commit@v1
with:
commit_message: |
Deploy myapp v1.2.3 to production [skip ci]
Automated deployment triggered by ${{ github.actor }}
file_pattern: 'overlays/production/*'
max_retries: 5- id: commit
uses: skyhook-io/git-sync-commit@v1
with:
commit_message: 'Update version to ${{ github.ref_name }}'
file_pattern: 'VERSION package.json'
- name: Create deployment
if: steps.commit.outputs.committed == 'true'
run: |
echo "Deploying commit ${{ steps.commit.outputs.commit_sha }}"
kubectl set image deployment/app app=myapp:${{ steps.commit.outputs.commit_sha }}- name: Generate documentation
run: npm run docs:generate
- id: commit
uses: skyhook-io/git-sync-commit@v1
with:
commit_message: 'Update generated documentation [skip ci]'
file_pattern: 'docs/**/*'
- name: Notify on changes
if: steps.commit.outputs.committed == 'true'
run: |
echo "Documentation updated in commit ${{ steps.commit.outputs.commit_sha }}"| Input | Description | Required | Default |
|---|---|---|---|
commit_message |
Commit message | Yes | - |
file_pattern |
Files to stage for commit (e.g., ".", ".yml", "path/to/files/") | No | . |
path |
Working directory for git operations | No | . |
commit_user_name |
Git committer name | No | github-actions[bot] |
commit_user_email |
Git committer email | No | 41898282+github-actions[bot]@users.noreply.github.com |
max_retries |
Maximum number of push retry attempts (handles concurrent pushes) | No | 3 |
| Output | Description |
|---|---|
committed |
Whether a commit was created (true/false) |
commit_sha |
SHA of the created commit (empty if no commit) |
The action follows this workflow:
- Validate inputs - Ensures working directory exists and inputs are valid
- Stash changes - Safely stashes any uncommitted changes (including untracked files)
- Sync with upstream - Pulls latest changes using rebase to maintain linear history
- Restore changes - Pops the stash to restore your changes
- Stage files - Adds files matching the specified pattern
- Commit - Creates a commit if there are staged changes
- Push with retry - Attempts to push with automatic retry on failure:
- On push failure, rebases again and retries
- Continues up to
max_retriesattempts - Handles race conditions from concurrent workflows
name: Deploy to Environments
on:
push:
tags:
- 'v*'
jobs:
deploy:
runs-on: ubuntu-latest
strategy:
matrix:
environment: [dev, staging, production]
steps:
- uses: actions/checkout@v4
- name: Update manifests
uses: skyhook-io/kustomize-edit@v1
with:
overlay_dir: overlays/${{ matrix.environment }}
image: myapp
tag: ${{ github.ref_name }}
- name: Commit changes
uses: skyhook-io/git-sync-commit@v1
with:
commit_message: Deploy ${{ github.ref_name }} to ${{ matrix.environment }} [skip ci]
file_pattern: overlays/${{ matrix.environment }}/*
max_retries: 10 # Higher retries for parallel deploymentsname: Update Dependencies
on:
schedule:
- cron: '0 2 * * 1' # Weekly on Monday
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Update dependencies
run: npm update
- id: commit
uses: skyhook-io/git-sync-commit@v1
with:
commit_message: |
chore: update npm dependencies [skip ci]
Automated weekly dependency update
file_pattern: 'package.json package-lock.json'
- name: Create PR
if: steps.commit.outputs.committed == 'true'
run: |
gh pr create \
--title "Weekly dependency update" \
--body "Automated dependency update from commit ${{ steps.commit.outputs.commit_sha }}"- name: Clone deployment repo
uses: actions/checkout@v4
with:
repository: my-org/deployment-configs
path: deployment
- name: Update configs
run: |
cd deployment
./scripts/update-config.sh ${{ github.ref_name }}
- uses: skyhook-io/git-sync-commit@v1
with:
path: deployment
commit_message: Update configuration for ${{ github.ref_name }}
file_pattern: 'configs/**/*.yaml'To prevent infinite loops in CI/CD pipelines, add [skip ci] to your commit message:
- uses: skyhook-io/git-sync-commit@v1
with:
commit_message: |
Deploy version ${{ github.ref_name }} [skip ci]
This prevents the push from triggering the workflow again
file_pattern: 'deployment/*'This action is a direct replacement for hisco/safe-rebase-commit with enhanced features and Skyhook standards.
- Composite action: Embedded logic (no external script dependencies)
- Better validation: Input validation before operations
- Enhanced outputs: Returns commit status and SHA
- GitHub summaries: Visual summaries in Actions UI
- Skyhook branding: Consistent with other Skyhook actions
- Better error handling: Clear error messages and validation
Simply update your action reference:
# Before (hisco/safe-rebase-commit)
- uses: hisco/safe-rebase-commit@v1.0.1
with:
path: deployment
commit_message: Update env 'production' to version 'v1.2.3' [skip ci]
file_pattern: overlays/production/*
# After (skyhook-io/git-sync-commit)
- uses: skyhook-io/git-sync-commit@v1
with:
path: deployment
commit_message: Update env 'production' to version 'v1.2.3' [skip ci]
file_pattern: overlays/production/*All inputs are compatible, no changes needed!
- Authentication: Ensure your workflow has write permissions to the repository
permissions: contents: write
- Branch protection: The action respects branch protection rules
- Concurrent workflows: Use higher
max_retriesvalues when multiple workflows may push simultaneously - Linear history: Uses rebase instead of merge to maintain clean history
- Stash safety: Uncommitted changes are preserved during sync operations
- No changes = no commit: The action skips commit creation when there are no staged changes
This action requires the following permissions:
permissions:
contents: write # Required to push commitsThis usually means concurrent changes occurred. The action automatically handles this with retries. If you see this repeatedly, increase max_retries:
- uses: skyhook-io/git-sync-commit@v1
with:
commit_message: My commit
max_retries: 10 # Increase for high-concurrency scenariosCheck that:
- Your
file_patternmatches the changed files - The files are actually modified
- The action has the right
pathif using a subdirectory
Ensure your workflow has write permissions:
permissions:
contents: writeFor organization repositories, also check:
- Repository settings allow GitHub Actions to create and approve pull requests
- Branch protection rules allow the github-actions bot to push