This project automatically syncs files from one GitLab repository (Repo A) to another repository (Repo B) whenever a merge happens.
The system listens for GitLab webhook events, detects changed files, copies them to the target repository, creates a new branch, pushes the code, and automatically creates a Merge Request.
Repo A Merge
β
Webhook triggers app
β
Detect changed files
β
Copy files to Repo B
β
Create branch
β
Push code
β
Create Merge Request automatically
- Detects GitLab merge events automatically
- Syncs only changed files
- Preserves folder structure
- Creates sync branch automatically
- Pushes code to Repo B
- Creates Merge Request automatically
- Supports excluded paths
- Prevents unwanted overwrites
- Logging support included
Before running the project, install the following:
- Python 3.10+
- Git
- GitLab Account
- ngrok Account
You need:
- GitLab Personal Access Token
- Access to both repositories
repo-sync-automation/
β
βββ src/
β βββ main.py
β βββ git_manager.py
β βββ sync_engine.py
β βββ webhook_handler.py
β βββ mr_creator.py
β βββ conflict_handler.py
β βββ logger.py
β βββ config_loader.py
β
βββ config/
β βββ config.yaml
β
βββ tests/
β
βββ logs/
β
βββ requirements.txt
βββ docker-compose.yml
βββ Dockerfile
βββ .env
git clone <repo-url>
cd repo-sync-automationYou can use:
- CMD
- PowerShell
- VS Code Terminal
python -m venv venv
venv\Scripts\activatepython3 -m venv venv
source venv/bin/activatepip install -r requirements.txtCreate a file named .env in the project root folder.
Example:
GITLAB_TOKEN=your_gitlab_token
WEBHOOK_SECRET=your_webhook_secret- Open GitLab
- Go to:
Profile β Preferences β Access Tokens
- Create token with permissions:
- api
- read_repository
- write_repository
- Copy the token
- Paste it inside
.env
Open:
config/config.yaml
Example configuration:
app:
host: 0.0.0.0
port: 8000
source_repo:
name: repo-a
url: https://gitlab.com/username/repo-a.git
branch: main
target_repo:
name: repo-b
url: https://gitlab.com/username/repo-b.git
branch: main
sync:
working_dir: repos
sync_branch_prefix: sync
excluded_paths:
- .git/
- node_modules/
- __pycache__/
- docs/
merge_request:
target_branch: main
title_prefix: "Auto Sync"
logging:
file: logs/app.logOpen terminal inside the project folder.
Run:
python src/main.pyIf using FastAPI + Uvicorn:
uvicorn src.main:app --host 0.0.0.0 --port 8000GitLab webhooks cannot access:
localhost:8000
ngrok creates a public URL that forwards requests to your local machine.
Download from:
https://ngrok.com/
- Sign up
- Login
- Copy your auth token
ngrok config add-authtoken YOUR_TOKENngrok http 8000You will get a URL like:
https://abc123.ngrok-free.app
Webhook URL:
https://abc123.ngrok-free.app/webhook
Copy this URL.
Go to:
Settings β Webhooks
Example:
https://abc123.ngrok-free.app/webhook
Enable:
- Merge Request Events
Click:
Add Webhook
Open Repo B.
On the project homepage, look at the right sidebar.
You will see:
Project ID: 12345678
Copy this ID.
curl --header "PRIVATE-TOKEN: <token>" \
https://gitlab.com/api/v4/projectsPaste the Project ID inside:
.envconfig.yaml- or wherever your MR API logic uses it
Developer merges code into main branch.
β
GitLab sends webhook payload.
β
Application compares commits.
β
Only modified files are synced.
β
Example:
sync/20260515
β
Application pushes changes automatically.
β
MR gets created using GitLab API.
Creates FastAPI server.
app = FastAPI()Webhook endpoint:
@app.post("/webhook")GitLab sends webhook events here.
Handles Git operations.
- Clone repository
- Pull latest code
- Create branch
- Commit changes
- Push branch
Example logic:
if repo exists:
git pull
else:
git cloneCreates branch like:
sync/20260515
Runs:
git add .
git commitRuns:
git pushGitPython allows Python to control Git.
Responsible for file synchronization.
- Copy modified files
- Delete removed files
- Preserve folder structure
| Status | Meaning |
|---|---|
| A | Added |
| M | Modified |
| D | Deleted |
Example:
('M', 'hello.txt')Means:
Modified file
Uses:
git diff old_commit new_commitFor comparing commits.
Uses:
shutil.copy2()To preserve:
- file content
- metadata
Creates Merge Request automatically using GitLab API.
Without API:
- Manual MR creation needed
Sends HTTP POST request:
{
"source_branch": "sync/123",
"target_branch": "main",
"title": "Auto Sync"
}Prevents overwriting files blindly.
Scenario:
- Repo B already changed same file
Automation should avoid overwriting directly.
Initial approach:
Webhook SHA payload
Can sometimes be inconsistent.
Better approach:
Local HEAD comparison
OR
GitLab Merge Request Changes API
Comparison Table:
| Method | Reliability |
|---|---|
| Webhook SHA payload | Inconsistent |
| Local HEAD comparison | Stable |
Example terminal logs:
[INFO] Webhook received
[INFO] Cloning source repository
[INFO] Detecting changed files
[INFO] Copying updated files
[INFO] Creating sync branch
[INFO] Committing changes
[INFO] Pushing branch
[INFO] Creating Merge Request
[INFO] Sync completed successfully
- Ensure ngrok is running
- Verify correct port
Example:
ngrok http 8000Verify token permissions:
- api
- read_repository
- write_repository
Check:
GitLab β Settings β Webhooks
Verify:
- Correct URL
- Merge Request Events enabled
Reconfigure Git credentials.
Check:
git config --global user.name
git config --global user.emailCheck:
- Project ID
- Token permissions
- API endpoint
venv\Scripts\activatesource venv/bin/activatepip install -r requirements.txtpython src/main.pyuvicorn src.main:app --host 0.0.0.0 --port 8000ngrok http 8000docker build -t git-sync-automation .docker run -p 8000:8000 git-sync-automationApplication will run on:
http://localhost:8000
docker-compose up --builddocker-compose downBefore running Docker:
- Ensure
.envfile exists - Ensure
config/config.yamlis configured properly - Docker Desktop should be running
- Docker deployment
- Kubernetes support
- Multiple repo sync support
- Better conflict resolution
- UI dashboard
- Retry queue system
- Slack notifications
Developed for automated GitLab repository synchronization and Merge Request creation.
Designed for DevOps automation, CI/CD workflows, and repository management.