Tại sao phải tốn công đồng bộ code lên nhiều nơi?
Sau nửa năm “chinh chiến” với dự án outsource, mình rút ra bài học xương máu: Đừng bao giờ bỏ hết trứng vào một giỏ. Dù GitHub cam kết uptime 99.9%, nhưng thực tế những lúc bảo trì hay cáp quang quốc tế gặp sự cố, cả team 20 người ngồi chơi xào nước vì không thể push code là chuyện hoàn toàn có thể xảy ra.
Bên cạnh đó, nhiều khách hàng yêu cầu lưu trữ trên GitLab nội bộ để chạy CI/CD riêng. Trong khi đó, team dev lại mê GitHub Actions vì hệ sinh thái quá mạnh. Lúc này, Mirroring (soi gương) repository là giải pháp vẹn cả đôi đường. Code của bạn sẽ xuất hiện song song ở mọi nơi mà không cần gõ lệnh git push thủ công đến mỏi tay.
Mình từng thoát nạn nhờ thói quen này. Một đồng nghiệp mới lỡ tay git push --force đè nát branch develop. May mắn là server GitLab nội bộ đã mirror từ trước, giúp mình khôi phục toàn bộ lịch sử commit chỉ trong 5 phút. Nếu không có bản mirror đó, chắc cả team phải thức trắng đêm để vá víu lại code.
Khái niệm Mirror Repository: Không chỉ là sao chép
Nhiều bạn nhầm giữa việc thêm remote thứ hai và Mirroring. Lệnh git remote add chỉ đơn thuần là thêm một địa chỉ để đẩy code. Mirroring đúng nghĩa sẽ đồng bộ mọi thứ: từ tất cả các branch, tag cho đến toàn bộ lịch sử commit (commit history).
Có hai hình thức bạn cần phân biệt:
- Push Mirroring: Kho code gốc (Source) chủ động đẩy dữ liệu sang kho đích (Destination) ngay khi có thay đổi.
- Pull Mirroring: Kho đích sẽ định kỳ “ghé thăm” và kéo code từ kho gốc về.
Cách 1: Mirror thủ công bằng Git CLI (Dùng khi cần chữa cháy nhanh)
Đây là cách nhanh nhất để bạn đồng bộ dữ liệu mà không cần setup phức tạp. Chúng ta tận dụng flag --mirror của Git.
# 1. Clone repository gốc với flag --mirror
git clone --mirror https://github.com/user/repo-goc.git
# 2. Di chuyển vào thư mục vừa clone
cd repo-goc.git
# 3. Đẩy toàn bộ sang repository đích
git push --mirror https://gitlab.com/user/repo-dich.git
Cảnh báo: Lệnh git push --mirror cực kỳ quyền lực. Nó sẽ ghi đè hoàn toàn mọi thứ ở đích. Nếu bên đích có branch nào không tồn tại ở nguồn, Git sẽ xóa sạch chúng không thương tiếc.
Cách 2: Tự động hóa bằng GitHub Actions (Lựa chọn tối ưu)
Nếu GitHub là “đại bản doanh”, hãy để GitHub Actions tự động đẩy code sang GitLab/Bitbucket mỗi khi có ai đó merge Pull Request. Cách này chuyên nghiệp và rảnh tay hơn nhiều.
Bước 1: Thiết lập quyền truy cập
Để hai nền tảng “nói chuyện” được với nhau, mình khuyên dùng SSH Key vì độ bảo mật cao hơn Personal Access Token.
- Tạo một cặp SSH key mới (đừng dùng chung với key cá nhân của bạn).
- Thêm Public Key vào mục Deploy Keys (nhớ tick chọn quyền Write) trên GitLab/Bitbucket.
- Copy Private Key vào Secrets and variables > Actions của GitHub với tên
GITLAB_SSH_PRIVATE_KEY.
Bước 2: Cấu hình Workflow
Tạo file .github/workflows/mirror.yml. Đoạn script này sẽ kích hoạt mỗi khi có push vào branch chính.
name: Mirror to GitLab
on:
push:
branches: [ main, develop ]
jobs:
git-mirror:
runs-on: ubuntu-latest
steps:
- name: Checkout mã nguồn
uses: actions/checkout@v4
with:
fetch-depth: 0 # Phải lấy toàn bộ lịch sử mới mirror được
- name: Cài đặt SSH Key
run: |
mkdir -p ~/.ssh
echo "${{ secrets.GITLAB_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan gitlab.com >> ~/.ssh/known_hosts
- name: Push sang GitLab
run: |
git remote add gitlab [email protected]:username/project-mirror.git
git push --force --prune gitlab "refs/remotes/origin/*:refs/heads/*"
git push --force --tags gitlab
Flag --prune trong script giúp dọn dẹp các branch đã bị xóa ở GitHub, giữ cho repository đích luôn sạch sẽ.
Cách 3: Tận dụng tính năng Mirror có sẵn của GitLab
Nếu bạn muốn kéo code từ GitHub về (Pull Mirroring), GitLab bản Free hỗ trợ rất tốt. Đây là cách “lười” nhưng cực kỳ hiệu quả cho việc backup định kỳ.
- Truy cập dự án trên GitLab, chọn Settings > Repository.
- Mở mục Mirroring repositories.
- Nhập URL của GitHub (Dạng:
https://github.com/user/repo.git). - Chọn hướng đồng bộ là Pull.
- Điền GitHub PAT (Personal Access Token) vào phần Authentication.
Thông thường, GitLab bản miễn phí sẽ tự động cập nhật sau mỗi vài giờ. Nếu cần gấp, bạn có thể nhấn nút Refresh để đồng bộ ngay lập tức.
Những lưu ý “xương máu” khi vận hành
Sau nhiều lần setup cho các hệ thống lớn, mình rút ra 3 bài học quan trọng:
1. Chặn đứng vòng lặp vô tận
Tuyệt đối không thiết lập Mirror hai chiều kiểu A đẩy sang B rồi B lại đẩy ngược về A. Nếu không có bộ lọc, hai bên sẽ liên tục kích hoạt trigger của nhau, làm treo hệ thống CI/CD và tiêu tốn tài nguyên vô ích.
2. Xử lý file nặng (Git LFS)
Lệnh git push thông thường sẽ bỏ qua các file lớn. Nếu dự án của bạn chứa nhiều asset (ảnh, video, model AI), hãy đảm bảo đã cài đặt Git LFS trên cả hai môi trường và chạy git lfs fetch --all trước khi thực hiện mirror.
3. Đồng bộ quyền hạn
Mirror code không có nghĩa là mirror quyền truy cập. Khi có nhân sự mới, bạn cần add họ vào cả hai nền tảng nếu muốn họ có thể tham gia review code hoặc xem log CI/CD ở cả hai bên.
Tổng kết
Thiết lập Mirror Repository không chỉ đơn giản là sao lưu. Đây là chiến thuật thông minh để tận dụng thế mạnh của từng nền tảng: dùng GitHub để quản lý task, dùng GitLab để chạy pipeline trên server riêng nhằm tối ưu chi phí.
Đừng đợi đến lúc server gặp sự cố mới cuống cuồng tìm cách cứu dữ liệu. Chỉ mất khoảng 15-30 phút để setup, nhưng sự yên tâm mà nó mang lại cho dự án là vô giá.

