逐项目迁移计划
预检查为每个对象选择 Direct Transfer、保守 Git 同步、仅 Git 回退或阻止状态。
GitLab DumpGitHub · v0.0.2
GitLab 仓库迁移工具
通过 CLI 或桌面应用克隆仓库,并在 GitLab 实例间迁移项目。执行前可检查兼容性、迁移模式和警告。
JavaScript · MIT · 最近更新
仅 Git 回退不会迁移议题、合并请求、CI 密钥或其他 GitLab 平台资源。
gitlab-dump transfer plan …
source / platform
↓ preflight
↓ reviewed plan
↓ selected transfer mode
destination / archive
plan → run → status → report
GitLab Dump
预检查为每个对象选择 Direct Transfer、保守 Git 同步、仅 Git 回退或阻止状态。
Git 同步创建缺失的引用,并在检查祖先关系后执行快进更新。分叉会在结果中报告。
令牌来自环境变量或掩码输入,而非命令参数或包含凭据的远程地址。
GitLab 仓库迁移工具
执行前检查警告、选定模式和目标命名空间。
运行已审查的计划并保留报告;已有操作可按 run ID 恢复状态轮询。
01 / 安装
npm · gitlab-dump-cli · 0.2.0 ↗
npm install -g gitlab-dump-cli@0.2.0 && gitlab-dump --help02 / README
用于克隆 GitLab 群组和跨实例迁移项目的 CLI 与桌面应用,提供迁移计划和执行报告。
配置说明、使用示例和 API 参考。
以下为仓库的原始文档,未作翻译;上方的示例与入门说明已本地化。
GitLab Dump clones repositories and performs conservative transfers between GitLab instances. The CLI and Electron application are thin shells over the same @gitlab-dump/core workspace.
Project website · All projects by rekurt
Version 0.2 intentionally breaks the 0.1 CLI. Every operation now requires an explicit subcommand. PAT flags, PAT-bearing clone URLs, plaintext migration configs, MigrationExecutor, and git filter-branch are gone.
npm install -g gitlab-dump-cli@0.2.0
gitlab-dump --help
For programmatic use, install @gitlab-dump/core@0.2.0.
Both packages require Node.js 24; the desktop application is distributed separately.
git-lfs when repositories contain LFS objects.git-filter-repo for history rewrite.Node 24 is an Active LTS line through October 2026 (Node.js release schedule). Electron 43 is a supported stable line (Electron schedule).
npm ci
npm run lint
npm test
npm run build
gitlab-dump clone
gitlab-dump transfer plan
gitlab-dump transfer run
gitlab-dump transfer status
gitlab-dump transfer cancel
gitlab-dump rewrite-history
Use --help on each command for its full option list.
PATs are accepted only from:
GITLAB_TOKEN as a shared fallback;GITLAB_SOURCE_TOKEN;GITLAB_DESTINATION_TOKEN;There are no token flags. Git authentication uses a temporary GIT_ASKPASS helper. Tokens are not added to command arguments, remote URLs, plans, reports, or ordinary configuration files. Legacy credential-bearing HTTP(S) origins are cleaned before an existing clone is updated.
export GITLAB_TOKEN='...'
gitlab-dump clone \
--url https://gitlab.example.com \
--group team/platform \
--clone-path ./repositories \
--report ./clone-report.json
Existing clones are changed only with --update, using git pull --ff-only.
export GITLAB_SOURCE_TOKEN='...'
export GITLAB_DESTINATION_TOKEN='...'
gitlab-dump transfer plan \
--source-url https://source.example.com \
--destination-url https://destination.example.com \
--source-path team/platform \
--source-type group \
--destination-namespace archive \
--out ./transfer-plan.json
gitlab-dump transfer run \
--plan ./transfer-plan.json \
--report ./transfer-report.json
A plan is schema-versioned and contains URLs, versions, paths, warnings, reasons, and one mode per entity. It never contains credentials.
| Mode | Meaning |
|---|---|
direct_transfer |
The destination entity is absent and GitLab Direct Transfer is compatible. |
git_sync |
The destination project exists; only conservative Git synchronization is allowed. |
git_only_fallback |
Direct Transfer is unavailable; an empty group/project skeleton is created, then Git is synchronized. |
blocked |
A preflight requirement failed and the entity is not changed. |
Git-sync creates missing branches and tags and fast-forwards branches only after proving ancestry. Divergent branches and conflicting tags are left unchanged. It never deletes refs or force-pushes. Existing GitLab metadata, issues, merge requests, and wiki pages are not manually merged. A source wiki Git repository and LFS objects are synchronized when present and when the required tools are available.
transfer run --run-id <id> resumes polling an already recorded bulk import instead of issuing another ambiguous POST. transfer status and transfer cancel use a private state file containing only IDs, URLs, status, and timestamps. Cancellation is state-driven; no persisted PID is signaled.
Preflight checks HTTPS, API access, source/destination versions, destination namespace access, Direct Transfer availability when observable, and local Git tools. GitLab documents these important prerequisites:
api scope and the account needs the required source/destination roles.See GitLab Direct Transfer prerequisites and the Bulk Imports API.
Direct Transfer creates copies. It does not copy every GitLab resource, and users are never created automatically. Membership and contribution mapping follows GitLab's current rules. Review GitLab's migrated items and limitations before production use.
Git-only fallback is not a full GitLab migration. It transfers repository refs, wiki Git data, and LFS data only; it does not transfer runners, CI/CD secrets, registry artifacts, instance data, issues, merge requests, or other platform resources.
Mapping files are strict and credential-free:
{
"schemaVersion": 1,
"mappings": [
{
"match": { "name": "Old Name", "email": "old@example.com" },
"replace": { "name": "New Name", "email": "new@example.com" }
}
]
}
Duplicate match emails, unknown fields, invalid emails, and control characters are rejected.
gitlab-dump rewrite-history \
--repository ./source.git \
--mapping ./history-mapping.json \
--output ./rewritten.git \
--dry-run
gitlab-dump rewrite-history \
--repository ./source.git \
--mapping ./history-mapping.json \
--output ./rewritten.git
The operation always clones a separate mirror, records changed commits/refs, creates a pre-rewrite Git bundle, and then invokes git filter-repo. It never rewrites the supplied repository in place.
Recovery is shown in the JSON result and has this form:
git clone --mirror "/path/to/rewritten.git.before-rewrite.bundle" restored.git
--push first runs and prints a fresh preview with the changed commit/ref counts, then requires the exact interactive confirmation phrase I UNDERSTAND THAT COMMIT SHAS WILL CHANGE. The desktop app likewise refuses a push unless the selected repository and mapping have a successful preview. Every changed ref is pushed separately with an exact --force-with-lease=<ref>:<old-sha>. A concurrent update or protected ref stops the operation; branch protection is never disabled automatically.
The Electron renderer is sandboxed and isolated. Navigation and renderer-created windows are denied. External OAuth pages are opened by the main process only after HTTPS/origin validation. On first load, legacy plaintext token fields from 0.1 settings are migrated into safeStorage (or session memory) and immediately removed from the ordinary settings object.
Desktop PATs and OAuth tokens use Electron safeStorage. If OS encryption is unavailable, secrets remain in memory for the current session and are not persisted. The renderer receives only hasToken flags, operation/resource IDs, safe plans, reports, statuses, and OAuth profile data. It never receives an OAuth access token or arbitrary filesystem authority.
Reports enumerate supported, skipped, and conflicting entities and preserve Direct Transfer correlation IDs and relation failures. Secrets are excluded.
0: successful operation or status query;1: failed operation or invalid input;2: partial result or blocked plan;130: canceled operation.npm run lint
npm run test:coverage
npm run build
npm run pack
npm audit --omit=dev --audit-level=high
CI uses npm ci and performs unsigned packaging smoke tests on Linux, macOS, and Windows. Code signing and notarization require user-owned certificates and remain a release task.
An opt-in GitLab opt-in smoke workflow exercises configured test instances. It requires prepared new-group, existing-project, cancellation, and intentional relation-failure fixtures; credentials come only from protected CI secrets.
MIT
GitLab Dump