Skip to content
open source · vector-migrate

Vector

Move your repos from Azure DevOps to GitHub — without losing your green squares.

An interactive CLI that migrates full Git history and rewrites your old corporate identity to your personal, verified one — so years of real work light up your contribution graph again, at their original dates.

  • Interactive
  • Zero-Token
  • Non-Destructive
View on GitHubnpm

$ npx vector-migrate— no install required

contribution graph
identity rewrittenhistory restored

The problem

A naïve migration quietly costs you four things.

Moving repos to GitHub looks like a plain git push — until your graph goes dark, a token leaks, a big repo stalls, or one oversized file kills the push at the very end. Vector is built around exactly these failure modes.

The Contribution Graph Wipeout

GitHub only lights up your contribution graph for commits whose author email is verified on your account. A normal migration carries corporate-email commits over as unattributed “ghosts,” so months or years of real work never show up as green squares. Vector rewrites your old corporate identity to your personal, verified one — and by default leaves everyone else untouched. Migrating a shared repo? Map your whole team in the same flow; each developer keeps attribution at their original dates.

The Security Token Leak

Pasting a Personal Access Token into a clone URL or config leaks it into shell history, .git/config, and CI logs. Vector is zero-token by design: it authenticates over SSH keys only and reads config from environment variables or in-memory prompts that are never written to disk.

The HTTPS Push Freeze

Large histories routinely hang at Writing objects: 100% over HTTPS. Vector streams over a single persistent raw-SSH pipeline, so even big repos transfer reliably.

The 100 MB Wall

GitHub hard-rejects any file over 100 MB found anywhere in history — and only at the final push, after the whole mirror and rewrite are done. One stray build artifact or .AppImage can sink an otherwise-perfect migration with a cryptic GH001 error. Vector scans your full history before pushing, names each offending file and size, and — by default in --force/CI — strips them from history (or moves them to Git LFS), so the push just succeeds. No surprise failure at the finish line.

How it works

Three stages, fully deterministic.

Source mirror in, staging copy rewritten, ancestry-aware push out. The same inputs always produce the same result.

01

Azure DevOps

Mirror / fetch

Mirror the full history from Azure DevOps into a pristine local source mirror — every branch, every commit, untouched.

$git fetch --mirror

02

Local staging copy

Rebuild + rewrite

Rebuild a disposable staging copy with git-filter-repo --mailmap — deterministically mapping your old email to your new identity. Unmapped authors stay exactly as they were — and you can remap teammates too when migrating a shared repo.

$git filter-repo --mailmap

03

GitHub

Ancestry-aware push

Push per branch over SSH — create, no-op, fast-forward, skip-if-ahead, or confirm-on-divergence. Vector never overwrites what is already on GitHub.

$ssh push --per-branch

One tool, three modes

The flow above is the default Azure-to-GitHub path, but Vector isn’t only an Azure tool. The same deterministic engine runs three migration modes — pick one with --mode.

A

Azure DevOps → GitHub

Full history with your old corporate identity rewritten to your verified one.

B

Azure DevOps → GitHub

Mirror-only — every commit carried over verbatim, nothing rewritten.

C

GitHub → GitHub

Move or re-attribute history between accounts.

Incremental by design

Re-run any time new commits land on Azure. Vector fetches only the delta, keeps identical SHAs for commits already pushed, fast-forwards the new ones, and refuses to clobber a diverged remote unless --force is passed.

createno-opfast-forwardskip-if-aheadconfirm-on-divergence

Quick start

Run it in two commands.

Install the one system dependency, then run the interactive wizard. There is nothing to configure by hand and no scripts to edit — Vector prompts you through it.

Requirements: Node.js ≥ 18, git, and git-filter-repo.

Requires SSH access to GitHub — run vector-migrate --check to verify.

New here? Run vector-migrate --doctor for a full PASS/FAIL environment check (or --check for a quick verify) — it confirms git and git-filter-repo are installed and prints exact, OS-specific install instructions if anything is missing.

bash
brew install git-filter-repo
npx vector-migrate

Prefer a global install? npm install -g vector-migrate, then run vector-migrate anywhere.

Automation

Run it unattended in CI

Every interactive prompt also has a flag and an environment variable, so you can skip the wizard entirely. Add --sync to re-run incrementally, --dry-run to preview without pushing, or --json for machine-readable output.

bash
vector-migrate --non-interactive \
  --azure-url  "https://org@dev.azure.com/org/Project/_git/Repo" \
  --github-ssh "git@github.com:you/your-repo.git" \
  --old-email  "you@old-corp.com" \
  --new-name   "your-github-username" \
  --new-email  "you@personal.com" \
  --branch master --branch main
bash
# GitHub → GitHub, auto-handle >100 MB files, and skip the rewrite if you're not a contributor:
vector-migrate --force \
  --mode c \
  --source "git@github.com:old-org/repo.git" \
  --dest   "git@github.com:you/repo.git" \
  --on-large-file strip \
  --skip-identity

See the full flag & environment-variable reference in the README →

Why it’s safe

Safe by construction, not by convention.

Zero-Token

SSH keys only. No Personal Access Token ever touches your shell history, config, or disk.

Non-Destructive

Vector never overwrites GitHub. A diverged remote requires an explicit --force.

Deterministic SHAs

Commits already pushed keep identical hashes on every subsequent run.

Incremental

Re-run as work continues on the source; only the new delta is fetched and pushed.

Verified, not assumed

After every push, Vector re-checks the destination against your migrated history across three axes — the full ref set (branches and tags), every ref-tip SHA, and the reachable commit count — and refuses to report success on any mismatch. You don't have to trust that it worked; it proves it.

Never the wrong person

Vector only rewrites an author into your identity when it actually matched you — by email, name, git config, or your GitHub username. Migrating a repo you didn't contribute to? It detects that and skips the rewrite, keeping every author untouched, instead of making you pick a stranger.

Solo or team — one auto-detecting flow

It scans every author, defaults to mapping just you, and lets you remap teammates when you need to.

Ready to bring your green squares with you?

Migrate your Azure DevOps history to GitHub with full attribution — interactive, zero-token, and non-destructive.