A GitHub Action that syncs pull requests with their target branches and uses AI to resolve conflicts.
-
Install the GitHub App — Install Merge Mate on your repository. Select "Only select repositories" for least-privilege access. The app appears as GitKraken Services on all GitHub UI surfaces.
After installing, GitHub redirects to your account settings. Return here to continue setup.
-
Get an API key — Go to Settings, sign in, and create an API key.
-
Add the key to GitHub Secrets — In your repository, go to Settings → Secrets and variables → Actions → New repository secret. Name it
MERGE_MATE_API_KEYand paste the key. -
Add workflow files — Create the YAML files below manually (the app does not generate them automatically).
If you need Merge Mate to push to branches that live in forks, especially private forks, plan the fork credential path up front:
- Install the GitKraken App on the fork owner too, and grant it access to the fork repository.
- Or provide
fork-push-tokenin both the sync and review workflows.
Create two workflow files in your repository:
.github/workflows/merge-mate.yml — syncs all PRs when the target branch is updated:
name: Merge Mate Sync
on:
push:
branches: [main] # ← replace with your default branch
concurrency:
group: merge-mate-sync-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: write
pull-requests: write
id-token: write
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: gitkraken/merge-mate-action/sync@v0.2
with:
ai-api-key: ${{ secrets.GK_AI_PROVISIONER_TOKEN }}.github/workflows/merge-mate-review.yml — handles apply/undo via PR checkbox or manual trigger:
name: Merge Mate Review
on:
issue_comment:
types: [edited]
workflow_dispatch:
inputs:
pr-number:
description: "PR number to process"
required: true
type: number
action:
description: "Action to perform"
required: true
type: choice
options:
- apply
- undo
permissions:
contents: write
pull-requests: write
id-token: write
concurrency:
group: merge-mate-review-${{ github.event.issue.number || inputs.pr-number }}
cancel-in-progress: false
jobs:
review:
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event.issue.pull_request && github.event.sender.type != 'Bot')
runs-on: ubuntu-latest
steps:
- uses: gitkraken/merge-mate-action/review@v0.2
with:
pr-number: ${{ inputs.pr-number }}
action: ${{ inputs.action }}When the target branch is updated, sync runs automatically. PR comments appear with diff preview and checkboxes. You can also manually trigger apply/undo from the Actions tab using workflow_dispatch or via the Conflict viewer link in the PR message.
These Quick Start workflows omit github-token on purpose and rely on GitKraken App authentication via OIDC, so they require permissions: id-token: write. If you prefer to use ${{ github.token }} or a PAT instead, pass it explicitly as github-token.
If your repository receives PRs from private forks, read Fork Pushes before relying on the default setup. Installing the app only on the base repository is not always enough to push back to fork branches.
- Flexible Sync — Rebase (linear history) or Merge (merge commits)
- AI Conflict Resolution — Automatic conflict resolution with AI
- Safe by Default — AI resolutions stored in hidden refs until approved; clean rebases are applied directly
- Parallel Processing — Configurable concurrency
- Detailed Reports — PR comments with diffs, GitHub Summary
When the target branch updates, Merge Mate rebases or merges all open pull requests that target that branch.
The outcome depends on the apply-policy and confidence-threshold settings:
| Apply Policy | Clean Rebase (no conflicts) | AI-Resolved Conflicts |
|---|---|---|
auto (default) |
Pushed to PR branch | Pushed if confidence ≥ threshold, otherwise saved to hidden ref for review |
resolved-only |
Skipped (no push) | Same as auto |
review |
Skipped (no push) | Saved to hidden ref for review |
dry-run |
No push, report only | No push, report only |
The default confidence-threshold is 100. Merge Mate does not automatically apply changes unless the AI is fully confident.
To allow automatic application of high-confidence resolutions, lower the value (for example, 80).
When Merge Mate saves a resolution to a hidden ref, it posts a pull request comment with:
- A diff preview
- An Apply checkbox
Select Apply to trigger the review workflow and push the resolution to the pull request branch.
Select Undo to revert the change.
Both actions force-push to the pull request branch. If you have a local checkout, run:
git fetch && git reset --hard origin/<branch>| Input | Default | Description |
|---|---|---|
github-token |
— | GitHub token for authentication. If omitted, Merge Mate falls back to GitKraken App authentication via OIDC. |
fork-push-token |
— | Explicit token used only to probe/push fork branches when the primary token cannot access the fork |
mode |
rebase |
rebase or merge |
signing-mode |
off |
off or ssh. Enables SSH signing capability, but Merge Mate only signs when policy requires it |
pr-filter |
— | YAML filter for selecting PRs: ids, target-branches, created, updated, authors (supports @org/team-slug tokens) |
concurrency |
3 |
Maximum number of PRs to process in parallel |
apply-policy |
auto |
auto — apply above threshold. resolved-only — same but skip clean rebases. review — save non-clean results to hidden refs for review and skip clean rebases. dry-run — no push |
confidence-threshold |
100 |
Minimum AI confidence (0–100) to auto-apply. 100 = only when fully confident |
ai-provider |
none |
AI provider: none | gitkraken |
ai-model |
— | AI model identifier (provider-specific) |
ai-api-key |
— | API key or token for the AI provider |
ai-api-base |
— | Custom API base URL |
exclude-files |
see below | Newline-separated glob patterns for files to exclude from AI resolution |
diff-viewer-base-url |
https://gitkraken.dev |
Base URL for the diff viewer |
telemetry |
true |
Enable telemetry and error tracking |
log-level |
info |
error | warn | info | debug |
Set signing-mode: ssh when you need Merge Mate to preserve trust signals on rewritten commits.
For the full setup flow, see SSH_SIGNING.md.
- Existing signed commits in a PR are preserved by re-signing rewritten commits.
- Branches that require signed commits are handled automatically when the bot can sign.
- If signing is required but the runner cannot sign safely, Merge Mate stores the rebased result in hidden refs and posts manual re-sign instructions instead of exposing the normal apply checkbox.
- Create or reuse the GitHub account that will appear as the committer.
- Generate a passphrase-less SSH key for signing:
ssh-keygen -t ed25519 -C "merge-mate[bot]@users.noreply.github.com" -f merge-mate-signing- Add the public key from
merge-mate-signing.pubto the bot GitHub account as a signing key. - Verify that the committer email is a verified email on that same GitHub account.
- Store the private key as a repository or organization secret.
Provide signing secrets and committer identity through workflow env:
jobs:
sync:
runs-on: ubuntu-latest
env:
MERGE_MATE_SSH_SIGNING_KEY: ${{ secrets.MERGE_MATE_SSH_SIGNING_KEY }}
MERGE_MATE_GIT_COMMITTER_NAME: merge-mate[bot]
MERGE_MATE_GIT_COMMITTER_EMAIL: merge-mate[bot]@users.noreply.github.com
steps:
- uses: gitkraken/merge-mate-action/sync@v0.2
with:
signing-mode: sshMERGE_MATE_SSH_SIGNING_KEY must contain the private key. Merge Mate derives the public key on the runner and uses it only for commit signing. For now, only passphrase-less SSH keys are supported.
If Merge Mate warns that GitHub did not verify rewritten commits:
unknown_key: upload the SSH public key to the bot account as a signing key.not_signing_key: remove and re-add the key as a signing key instead of an authentication key.unverified_email: makeMERGE_MATE_GIT_COMMITTER_EMAILmatch a verified email on the bot account.no_user: make sure the committer email belongs to a GitHub account.malformed_signature: re-save the private key secret exactly as exported, including the final newline.
| Input | Default | Description |
|---|---|---|
github-token |
— | GitHub token for authentication. If omitted, Merge Mate falls back to GitKraken App authentication via OIDC. |
fork-push-token |
— | Explicit token used only to probe/push fork branches when the primary token cannot access the fork |
pr-number |
— | PR number to process (required for workflow_dispatch) |
action |
— | apply or undo (required for workflow_dispatch) |
telemetry |
true |
Enable telemetry and error tracking |
log-level |
info |
error | warn | info | debug |
Fork PRs are resolved with a separate pre-push credential flow. This is the part that usually breaks on private forks.
When Merge Mate rewrites a PR branch, it must push back to the repository that owns that branch.
- For same-repo PRs, that is the base repository.
- For fork PRs, that is the fork repository, not the base repository.
- A GitHub App installation token only works on repositories included in that installation.
That means installing the app only on the base repository does not automatically let it push to a private fork owned by another user or organization.
For fork pushes, Merge Mate resolves credentials in this order:
- If the primary source is a regular
github-tokenor PAT, probe that token against the fork repository first. - If the primary source is the GitKraken App, request a fork-specific installation token for the fork owner first.
- If the selected primary path cannot verify fork access, try
fork-push-token. - If none of those paths can verify fork access, do not push the fork branch automatically.
The same credential resolver is used in both sync and review, so any credential you choose for fork pushes should be available to both workflows.
The credential resolver is shared, but the fallback behavior is intentionally different:
syncfalls back to hidden refs when it cannot find a valid fork push path, so the PR can still be processed and reviewed.reviewdoes not silently downgrade the apply/undo request; it fails with a precise message when there is no valid way to push the fork branch.- If a fork push was already rejected after access was verified, the PR comment suppresses the interactive apply checkbox and leaves manual commands instead of offering the same retry again.
- If your primary
github-tokenor PAT already has direct access to the fork repository, Merge Mate can use that token directly and you may not need extra fork-specific credentials. - Preferred path: install the GitKraken App on the account or organization that owns the fork and grant it access to that fork repository.
- Explicit fallback: provide
fork-push-tokenwith access to the fork branch. This is the most predictable option when you cannot install the app on the fork owner. - Opportunistic option:
${{ github.token }}can be passed asfork-push-token, but GitHub documentsGITHUB_TOKENas scoped to the workflow repository, so this is best-effort rather than a guaranteed solution for private forks.
If the fork is user-owned, enabling "Allow edits from maintainers" can help in some setups, but it does not grant a GitHub App installation token access to a private fork by itself.
If you use ${{ github.token }} as fork-push-token, the workflow still needs permissions: contents: write.
- App not installed on the fork owner: Merge Mate cannot mint a fork installation token, so it falls back to
fork-push-tokenif provided. fork-push-tokenmissing or invalid: Merge Mate keeps the rebased result in hidden refs and posts manual commands instead of pushing the branch.- Probe inconclusive, for example rate limits or transient network failures: Merge Mate treats that as uncertain access and avoids claiming the fork is definitely unreachable.
- Push rejected after access was verified: this usually means branch protection, repository rules, or token capabilities still block the final push. In that case the PR comment disables the interactive apply retry and shows manual commands instead.
- If you choose
fork-push-token, use the same secret in both the sync and review workflows. - If you use a PAT, it needs access to the fork repository and permission to update the source branch.
- If you use
${{ github.token }}asfork-push-token, treat it as a convenience fallback, not as the primary solution for private forks. - If your reviewers depend on the checkbox-based apply flow, prefer installing the app on the fork owner or providing a reliable
fork-push-token; otherwise the branch may stay in hidden refs and require manual apply.
By default, Merge Mate excludes lock files, minified bundles, generated code, and build artifacts from AI resolution.
For conflicted lock files, Merge Mate uses the target branch version.
Custom patterns are appended to the defaults:
- uses: gitkraken/merge-mate-action/sync@v0.2
with:
exclude-files: |
**/vendor/**
**/fixtures/**| Permission | Why |
|---|---|
contents: write |
Push rebased branches and hidden refs |
pull-requests: write |
Post and update PR comments |
id-token: write |
Request OIDC tokens for GitKraken services (GitHub App auth fallback and GitKraken AI) |
id-token: write is required whenever you omit github-token, and also when using ai-provider: gitkraken. If you provide github-token explicitly and do not use GitKraken AI, you can omit it.
See EXAMPLES.md for ready-to-use workflow presets: apply policies, dry run, manual trigger, PR filtering, SSH signing, fork push workflows, and more.
- Committer identity — All commits pushed by Merge Mate show
gitkraken-services[bot]as the committer. The original author is preserved. - Commit signatures — Rewritten commits lose their original signatures. If your branch protection requires signed commits, you may need to re-sign after apply.
- Force push — Apply, undo, and direct sync all force-push to the PR branch. Coordinate with co-authors before applying if they have local commits not yet pushed on the same branch.
- Private forks — The GitHub App must be installed on each fork individually. Installing it only on the base repository is not enough to push to fork branches.
"APIKey is required" — The secret is missing or misconfigured. Verify that MERGE_MATE_API_KEY exists in Settings → Secrets and variables → Actions, the name matches exactly (case-sensitive), and the token is valid.
"No PRs processed" — Check that the branches trigger in your workflow matches the branch that was actually pushed. If you use pr-filter, verify the filter does not exclude all open PRs.
Permission errors on push — Ensure contents: write is set in the workflow permissions block. Repository-level settings (Settings → Actions → General → Workflow permissions) must also allow write access.
Apply/Undo checkbox does nothing — The review workflow must be set up separately (see Quick Start). Check that .github/workflows/merge-mate-review.yml exists and the issue_comment trigger is enabled.
Over time, hidden refs (refs/merge-mate/*) accumulate in your repository. To clean them up, add a scheduled workflow:
Warning
This deletes all merge-mate refs including pending resolutions awaiting review. Any unapplied AI conflict resolutions will be lost.
name: Merge Mate Cleanup
on:
schedule:
- cron: "0 3 * * 0" # weekly on Sunday at 3am UTC
workflow_dispatch:
permissions:
contents: write
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Delete stale merge-mate refs
run: |
git ls-remote origin 'refs/merge-mate/*' | awk '{print $2}' | while read ref; do
git push origin --delete "$ref" 2>/dev/null || true
doneThis deletes all hidden refs. Applied or undone resolutions are already on the PR branch, so removing the refs is safe.
For v0.x.y (pre-release):
- Pin to
@v0.2— patches within the same minor version - Breaking changes may occur between minors
For v1+ (stable):
- Pin to
@v1— all compatible updates