Skip to main content

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).

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)​

  1. Click + Add Mirror.
  2. Enter the GitHub repository URL (https://github.com/owner/repo).
  3. Paste your GitHub PAT.
  4. Set the target branch on GitHub (default: main).
  5. Choose whether to squash commits on feature branch pushes.
  6. 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.

MethodPathDescription
GET/api/projects/:id/mirrorsList configured mirrors
POST/api/projects/:id/mirrorsCreate mirror (validates credentials)
PATCH/api/projects/:id/mirrors/:mirrorIdUpdate mirror
DELETE/api/projects/:id/mirrors/:mirrorIdRemove mirror
POST/api/projects/:id/mirrors/:mirrorId/preview-messageGenerate AI commit message
POST/api/projects/:id/mirrors/:mirrorId/pushPush feature branch
POST/api/projects/:id/mirrors/:mirrorId/push-defaultPush default branch
POST/api/projects/:id/mirrors/:mirrorId/push-cancelledRecord a cancelled push attempt
GET/api/projects/:id/mirrors/:mirrorId/push-logPush audit log