How I Automated a Full GitLab Migration Using Bash (Real Case Study + Scripts)
Source: Dev.to

Migrating multiple repositories between GitLab instances can quickly become a complex and repetitive process — especially when dealing with groups, subgroups, CI/CD pipelines, variables, tags, and issues.
To solve this challenge efficiently, I developed a collection of Bash automation scripts used to migrate projects from a self‑hosted GitLab Community Edition to GitLab Enterprise (gitlab.com). This post summarizes the approach, structure, and benefits, and the full toolkit is now open‑source for the community.
Why Automate the Migration?
When migrating large environments, manual work becomes:
- ❌ Time‑consuming
- ❌ Error‑prone
- ❌ Hard to track or repeat
Automation ensures the process is:
- ✔️ Repeatable
- ✔️ Auditable
- ✔️ Safe
- ✔️ Scalable
- ✔️ Faster
What’s Included in the Toolkit?
| Script | Purpose |
|---|---|
clone-projects.sh | Clones all repositories from the source GitLab group |
replace_gitlab-ci.sh | Updates .gitlab-ci.yml references for the new paths |
push-projects.sh | Pushes branches and tags to the target GitLab instance |
migrar-variaveis.sh | Migrates group‑level environment variables via API |
migrar_issues.sh | Migrates issues and comments preserving metadata |
delete-issues.sh | Deletes issues when resetting staging/testing |
gitlab-clone-recursive.sh | Clones nested groups and subgroups recursively |
gitlab-push-recursive.sh | Pushes repositories and recreates missing subgroups automatically |
Each script contains:
- Validation logic
- Logging
- Backup behavior
- Idempotent execution (safe to rerun)
How It Works (High‑Level Workflow)
- Clone repositories from the source GitLab.
- Apply CI/CD path replacements if needed.
- Push repositories (branches + tags) to the destination.
- Migrate variables, issues, and metadata.
- Validate and finalize the migration.
This flow supports incremental migration, useful for large environments.
Full Source Code
The complete source code is available in the public repository (link omitted for brevity).
Final Result
Using this automation, we achieved:
- ✅ Complete migration of all repositories
- ✅ Preservation of history, branches, and tags
- ✅ Reuse of CI/CD pipelines with minimal manual work
- ✅ Controlled and repeatable process
Final Note
This project was created after a real‑world GitLab migration highlighted the lack of clear, complete, and automated guidance—especially one that covers repositories, CI/CD files, variables, branches, tags, and issues in a structured and safe way.
The first version was built in Bash because of a strong background in Linux automation and shell scripting, allowing rapid development and reliable migrations. The long‑term goal is to refactor the solution into Python, making it more flexible, maintainable, and modular for future improvements.
If you are interested in contributing, improving features, or helping with the Python rewrite, feel free to jump in—collaboration is welcome.
If this project saved you time, inspired a better approach, or helped even a little, publishing it was worth it. Together, we make the DevOps community stronger. 🚀
If you’re planning or performing a GitLab migration, feel free to fork, adapt, and contribute improvements.
Feedback and collaboration are welcome!