GitHub Mirror Sync
The GitHub Mirror Sync feature allows you to push changes from your canonical GitLab-backed project to an external GitHub repository on demand. GitLab remains the system of record; GitHub is treated as a destination mirror.
Model
GitLab is canonical. GitHub is a mirror. All development happens on GitLab branches. Pushes to GitHub are always user-initiated and one-directional (GitLab → GitHub). GitHub history may be rewritten (squashed) and should not be treated as a source of truth.
Default Branch Sync
The default branch (e.g. develop) can be pushed to GitHub via a fast-forward push. If the remote branch has diverged, the UI surfaces an error and offers a force-with-lease opt-in that requires explicit confirmation.
Feature Branch Sync (squashed)
Feature branches are squashed before pushing to GitHub. Each push window creates a single commit on the GitHub branch:
- First push: all commits from the merge-base between the feature branch and the GitHub default branch are squashed.
- Subsequent pushes: only commits added since the last successful push are squashed into a new commit appended on top of the previous one.
Squashing can be disabled per-mirror for projects that do not require commit hygiene.
AI-Generated Commit Messages
Before pushing a feature branch, the system proposes a conventional-commits-style commit message based on the diff and commit log. You can:
- Accept the suggestion as-is.
- Edit the subject and/or body.
- Cancel the push entirely.
The AI-suggested message and the final (possibly edited) message are both recorded in the push audit log.
Security: Stored Personal Access Tokens
GitHub PATs are stored encrypted at rest using AES-256-GCM. The raw token is:
- Never logged.
- Never returned in API responses after initial creation (only a masked version — last 4 characters — is returned).
Recommended PAT Scope
Create a fine-grained PAT scoped to the specific target repository with only Contents: Read and write permission. This limits blast radius if the token is ever compromised.
Do not use a classic PAT with broad repo scope unless the repository is already public.
Configuration
Adding a Mirror (Project Settings → Integrations → External Mirrors)
- Click + Add Mirror.
- Enter the GitHub repository URL (
https://github.com/owner/repo). - Paste your GitHub PAT.
- Set the target branch on GitHub (default:
main). - Choose whether to squash commits on feature branch pushes.
- Click Add Mirror — the token is validated against the GitHub API before saving.
Editing a Mirror
Click Edit next to the mirror. Leave the PAT field blank to keep the existing token.
Removing a Mirror
Click Remove. This deletes the mirror configuration but does not affect the remote GitHub repository.
API Reference
All endpoints require project membership. Push endpoints enforce per-project rate limiting (10 pushes per 5 minutes). The preview-message endpoint uses a separate, higher quota (30 previews per 5 minutes) so that previewing a commit message does not consume push quota.
| Method | Path | Description |
|---|---|---|
GET | /api/projects/:id/mirrors | List configured mirrors |
POST | /api/projects/:id/mirrors | Create mirror (validates credentials) |
PATCH | /api/projects/:id/mirrors/:mirrorId | Update mirror |
DELETE | /api/projects/:id/mirrors/:mirrorId | Remove mirror |
POST | /api/projects/:id/mirrors/:mirrorId/preview-message | Generate AI commit message |
POST | /api/projects/:id/mirrors/:mirrorId/push | Push feature branch |
POST | /api/projects/:id/mirrors/:mirrorId/push-default | Push default branch |
POST | /api/projects/:id/mirrors/:mirrorId/push-cancelled | Record a cancelled push attempt |
GET | /api/projects/:id/mirrors/:mirrorId/push-log | Push audit log |