How I Automated a Full GitLab Migration Using Bash (Real Case Study + Scripts)

Published: (December 1, 2025 at 08:59 PM EST)
2 min read
Source: Dev.to

Source: Dev.to

Cover image for How I Automated a Full GitLab Migration Using Bash (Real Case Study + Scripts)

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?

ScriptPurpose
clone-projects.shClones all repositories from the source GitLab group
replace_gitlab-ci.shUpdates .gitlab-ci.yml references for the new paths
push-projects.shPushes branches and tags to the target GitLab instance
migrar-variaveis.shMigrates group‑level environment variables via API
migrar_issues.shMigrates issues and comments preserving metadata
delete-issues.shDeletes issues when resetting staging/testing
gitlab-clone-recursive.shClones nested groups and subgroups recursively
gitlab-push-recursive.shPushes 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)

  1. Clone repositories from the source GitLab.
  2. Apply CI/CD path replacements if needed.
  3. Push repositories (branches + tags) to the destination.
  4. Migrate variables, issues, and metadata.
  5. 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!

Back to Blog

Related posts

Read more »