Multi-provider, bidirectional Git repository mirroring tool.
Supports CodeCommit, GitLab, GitHub with any-to-any mirroring via SQS polling and webhook receivers.
Event Sources Git-Bridge Targets
┌──────────────────────┐ ┌──────────────────┐
│ │ │ │
┌──────────────┐ │ EventBridge → SQS │──(poll)──▶ │ │──▶ GitLab
│ CodeCommit │──▶│ (referenceUpdated) │ │ │
└──────────────┘ │ + DLQ │ │ │──▶ GitHub
└──────────────────────┘ │ Mirror Svc │
│ │──▶ CodeCommit
┌──────────────┐ ┌──────────────────────┐ │ clone → push │
│ GitLab │──▶│ POST /webhook/gitlab│──(http)──▶ │ │──▶ ...
└──────────────┘ └──────────────────────┘ │ │
│ │
┌──────────────┐ ┌──────────────────────┐ │ │ ┌───────┐
│ GitHub │──▶│ POST /webhook/github│──(http)──▶ │ │──────▶│ Slack │
└──────────────┘ └──────────────────────┘ │ │ └───────┘
└──────────────────┘
| Source Provider | Event Delivery | Trigger |
|---|---|---|
| CodeCommit | EventBridge → SQS → long-polling | referenceUpdated event |
| GitLab | Push Webhook → POST /webhook/gitlab |
Push event |
| GitHub | Push Webhook → POST /webhook/github |
Push event |
- Multi-provider: CodeCommit, GitLab, GitHub (extensible via
Providerinterface) - Any-to-any: Any provider can mirror to any other provider
- Multi-repo: Configure multiple repositories in a single instance
- Bidirectional:
source-to-target/target-to-source/bidirectional - Loop detection: Skips notification on no-op push (already up-to-date), preventing redundant alerts in bidirectional sync
- Multi-SQS consumer: Support multiple SQS queues for multi-AWS region/account environments
- Dual event sources: SQS polling (CodeCommit) + HTTP webhooks (GitLab/GitHub)
- DLQ support: Failed SQS messages retry up to 5 times, then move to DLQ
- Notifications: Slack webhook on success/failure (see Slack App Setup)
- Incremental sync: Reuses existing mirror via
git fetch— full clone only on first run or fallback - Persistent cache: PVC-backed mirror directory survives pod restarts for fast recovery
- Cloud-native: K8s Deployment with liveness/readiness probes
- Language: Go 1.24+
- AWS SDK: aws-sdk-go-v2 (SQS consumer)
- Git: Incremental
git fetch --prune(withgit clone --mirrorfallback) /git push --force - Config: YAML with
${ENV_VAR}expansion (credentials only; repos defined directly) - CI/CD: GitHub Actions (test, release, changelog)
- Runtime: Kubernetes (Alpine-based Docker image)
git-bridge/
├── cmd/git-bridge/ # Entry point
├── internal/
│ ├── config/ # YAML config with env var expansion
│ ├── consumer/
│ │ ├── sqs.go # SQS consumer (CodeCommit events via EventBridge)
│ │ └── webhook.go # HTTP webhook consumer (GitLab/GitHub push events)
│ ├── mirror/ # Git mirror operations (incremental fetch/clone, push, direction-aware)
│ ├── provider/ # Git provider abstraction (CodeCommit, GitLab, GitHub)
│ ├── notify/ # Slack webhook notifications
│ └── server/ # HTTP server (health + webhook endpoints)
├── k8s/ # Kubernetes manifests (production, minimal comments)
│ ├── namespace.yaml
│ ├── secret.yaml # Credentials only (tokens, keys, passwords)
│ ├── configmap.yaml # config.yaml (repos defined directly, credentials via ${ENV_VAR})
│ ├── pvc.yaml # PersistentVolumeClaim for mirror cache (optional)
│ └── deployment.yaml # Deployment + Service + Ingress
├── examples/ # Example files with detailed comments
│ ├── config.yaml # App config example
│ ├── secret.yaml # K8s Secret example (placeholder values)
│ ├── configmap.yaml # K8s ConfigMap example
│ └── deployment.yaml # K8s Deployment + Service + Ingress example
├── .github/workflows/ # GitHub Actions (test, release, changelog, etc.)
├── cliff.toml # git-cliff changelog configuration
├── Makefile # Build, test, deploy commands
└── Dockerfile # Multi-stage build (golang → alpine)
Credentials are injected via environment variables (${VAR} syntax, expanded at startup). Repository definitions are written directly in the ConfigMap — no env vars needed for repos.
All env vars follow the
<TYPE>_<NAME>_<FIELD>pattern. See docs/naming-convention.md for the full naming convention guide.Example files with detailed comments are available in the examples/ directory. Use them as a starting point for your own configuration.
| Variable | Description | Required |
|---|---|---|
CODECOMMIT_<NAME>_REGION |
AWS region per CodeCommit provider (e.g. CODECOMMIT_EU_REGION) |
Yes* |
CODECOMMIT_<NAME>_GIT_USERNAME |
CodeCommit HTTPS Git username (e.g. CODECOMMIT_EU_GIT_USERNAME) |
Yes* |
CODECOMMIT_<NAME>_GIT_PASSWORD |
CodeCommit HTTPS Git password (e.g. CODECOMMIT_EU_GIT_PASSWORD) |
Yes* |
GITLAB_<NAME>_BASE_URL |
GitLab instance URL (e.g. GITLAB_MAIN_BASE_URL) |
Yes* |
GITLAB_<NAME>_TOKEN |
GitLab personal access token (e.g. GITLAB_MAIN_TOKEN) |
Yes* |
GITHUB_<NAME>_TOKEN |
GitHub personal access token (e.g. GITHUB_MAIN_TOKEN) |
Yes* |
SQS_<NAME>_QUEUE_URL |
SQS queue URL per consumer (e.g. SQS_EU_QUEUE_URL) |
Yes** |
SQS_<NAME>_REGION |
SQS region per consumer (e.g. SQS_EU_REGION) |
Yes** |
SQS_<NAME>_ACCESS_KEY |
AWS access key per consumer (e.g. SQS_EU_ACCESS_KEY) |
Yes** |
SQS_<NAME>_SECRET_KEY |
AWS secret key per consumer (e.g. SQS_EU_SECRET_KEY) |
Yes** |
WEBHOOK_GITLAB_SECRET |
X-Gitlab-Token verification (empty = skip) | No |
WEBHOOK_GITHUB_SECRET |
GitHub webhook secret for HMAC-SHA256 (empty = skip) | No |
SLACK_WEBHOOK_URL |
Slack incoming webhook URL (empty = disabled) | No |
CONFIG_PATH |
Config file path (default: /etc/git-bridge/config.yaml) |
No |
WORK_DIR |
Temp directory for git operations (default: /tmp/git-bridge) |
No |
* Required per provider. Follow the
<TYPE>_<NAME>_<FIELD>pattern.<NAME>is a free-form identifier — e.g.EU/USfor AWS services,MAIN/SECONDARYfor platform services. ** Required per SQS consumer. Follow theSQS_<NAME>_*pattern — e.g.SQS_EU_*,SQS_US_*,SQS_AP_*
Repos are defined directly in k8s/configmap.yaml under the repos: section. No environment variables or Secret changes needed — just add a new entry:
repos:
- name: my-new-repo
source: codecommit-eu
target: gitlab-main
source_path: my-new-repo
target_path: server/my-new-repo
direction: source-to-target| Direction | Description | Trigger | Example |
|---|---|---|---|
source-to-target |
Source → Target only | SQS (CodeCommit) or source webhook | CodeCommit → GitLab |
target-to-source |
Target → Source only | Target provider webhook required | GitLab → CodeCommit |
bidirectional |
Both directions | SQS + target webhook both required | CodeCommit ↔ GitLab |
Note:
target-to-sourceandbidirectionalrequire webhook configuration on the target provider (GitLab/GitHub). If using onlysource-to-targetwith CodeCommit as source, SQS (EventBridge) triggers automatically — no webhook setup needed.See docs/ADVANCE.md for all provider combinations and detailed configuration examples.
| Path | Method | Description |
|---|---|---|
/health |
GET | Liveness probe |
/ready |
GET | Readiness probe |
/webhook/gitlab |
POST | GitLab push event receiver |
/webhook/github |
POST | GitHub push event receiver |
See docs/API.md for detailed request/response specifications.
# Build binary
make build
# Run tests
make test
# Format & vet
make fmt vet
# Docker build
make docker-build# 1. Create namespace
kubectl apply -f k8s/namespace.yaml
# 2. Create secrets (edit secret.yaml values first!)
kubectl apply -f k8s/secret.yaml
# 3. Create PVC (optional), configmap and deployment
kubectl apply -f k8s/pvc.yaml # optional: for persistent mirror cache
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/deployment.yaml
# Verify
kubectl get pods -n git-bridge
kubectl logs -n git-bridge -l app=git-bridge -fmake restart # Restart deployment
make logs # Tail pod logs
make deploy # Apply all k8s manifestsWebhook setup is required when direction is
target-to-sourceorbidirectional. If using onlysource-to-targetwith CodeCommit as source, SQS triggers automatically — no webhook needed.
Configure individually for each target GitLab project. See docs/gitlab-webhook-setup.md for detailed setup guide.
- Go to GitLab project > Settings > Webhooks
- URL:
http://git-bridge.example.com/webhook/gitlab - Secret token: (match
WEBHOOK_GITLAB_SECRET) - Trigger: Push events
- Enable SSL verification: No (HTTP)
Configure individually for each target GitHub repository. See docs/github-webhook-setup.md for detailed setup guide.
- Go to GitHub repo > Settings > Webhooks > Add webhook
- Payload URL:
http://git-bridge.example.com/webhook/github - Content type:
application/json - Secret: (match
WEBHOOK_GITHUB_SECRET) - Events: Just the push event
- Add the repo entry to
k8s/configmap.yamlunderrepos::
- name: new-repo
source: codecommit-eu
target: gitlab-main
source_path: new-repo
target_path: server/new-repo
direction: source-to-target-
If using CodeCommit with EventBridge → SQS, add the repo name to your Terraform configuration.
-
Apply and restart:
kubectl apply -f k8s/configmap.yaml
kubectl rollout restart -n git-bridge deployment/git-bridgeNo changes to
secret.yamlordeployment.yamlare needed. If direction istarget-to-sourceorbidirectional, webhook setup is also required on the target provider (GitLab/GitHub) project. See Setting Up Webhooks.
Implement the Provider interface in internal/provider/:
type Provider interface {
CloneURL(repoPath string) string
Type() string
}Register it in provider.New().
| Document | Description |
|---|---|
| Naming Convention | Multi-provider naming convention guide |
| Advanced Config | All provider combinations and detailed examples |
| API Reference | Endpoint request/response specifications |
| GitLab Webhook | GitLab webhook setup guide |
| GitHub Webhook | GitHub webhook setup guide |
| Slack App Setup | Slack notification setup guide |
Issues and pull requests are welcome.
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Thanks to all contributors:
