The Done-It-Before Migration Playbook: Merged Diffs to a Contract Slate
Turn one from-to migration pair into a graded slate of 3 to 8 engineers, each with a dated merged-diff link, in about five working days.
Key takeaways
- In Refolk's index of professional profiles, 412 US profiles list AngularJS, React, and "migration" together, but only 10 list Webpack, Vite, and "migration", so profile keywords cannot source newer migrations.
- A migration counts as finished only when the manifest shows the old package gone at HEAD, the new package present, and the old package still absent 90 days later.
- GitHub's REST search returns at most 1,000 results per search, so split merged-PR queries into created: date windows until each window returns fewer than 1,000.
- Refolk's proposed grading cut-offs are Led at 50% or more of migration commits or authorship of the cut-over PR, Contributed at 10 to 49% or reviewer on 3 or more migration PRs, and Tourist below both.
- Roughly two-thirds of 133 popular GitHub repositories have a truck factor of two or fewer, so most migrations have one or two dominant authors worth finding.
- A signed contractor agreement does not settle worker status under California's ABC test, which applies to any work performed in California wherever the hiring company is based.
This playbook is for engineering managers, technical founders, and technical sourcers who have a time-boxed migration to run (AngularJS to React, webpack to Vite, .NET Framework to .NET 8) and need two or three engineers who have finished that exact job before. It uses the migration artifact itself as the search key: a merged manifest diff that removes the old dependency and keeps it removed. You end with a contract-ready slate of 3 to 8 people, each graded Led, Contributed, or Tourist with a dated evidence link, in about five working days.
Why profile keywords fail when you hire an engineer with migration experience
Profile keywords tell you who claims both stacks. They do not tell you who finished moving a codebase from one to the other, and they get thinner the newer the migration is. A repo history either shows the old dependency removed or it does not. A headline can't show that either way.
In Refolk's index of professional profiles, I counted people who list both the source and target skills and also put "migration" in their headline:
| Market / pair | Matching profiles | Top title (sample of 25) | Ratio vs US AngularJS→React |
|---|---|---|---|
| US, AngularJS + React | 412 | Staff Software Engineer (3) | 1.0 |
| UK, AngularJS + React | 58 | Senior Software Engineer (4) | 0.14 |
| US, Webpack + Vite | 10 | No title above 1 | 0.024 |
The ratios come from the counts: the US AngularJS pool is 7.1x the UK pool and 41.2x the US Webpack/Vite pool.
Two things follow from this.
- For older migrations, keywords give you volume without proof. 412 people is a sourcing list, not a shortlist. Nothing in that count separates the person who led a cut-over from the person who kept a half-migrated hybrid running for two years.
- For newer migrations, keywords give you almost nothing. Ten US profiles is too few to source from. One plausible reading, which is not established, is that people add older skills to their profiles first, so profiles lag the work. Either way, repo evidence is the only search key you can use for the newer pairs.
Look at the top titles too: Staff Software Engineer and Senior Software Engineer, not "migration consultant". The people who did this work describe themselves by their level, not by the job. That is the gap Refolk is built to close. You ask for the engineers who authored the merged PR, not the ones whose headline happens to mention both stacks.
Listing both stacks proves exposure. A manifest diff that removes the old package and stays that way proves completion.
What counts as proof that a migration finished
A migration is proven finished when the project's manifest shows the old package removed and the new package present, and the old package is still absent 90 days later. Anything less proves exposure or an attempt, not completion.
A manifest is the file that declares a project's dependencies: package.json for npm projects, a .csproj file for .NET, a requirements file for Python. A token is the exact package name as it appears in that file, such as angular or webpack going out and react or vite coming in.
Each condition proves something different, and each one can mislead you:
- Old token removed. This proves the team actually cut the dependency rather than adding the new one next to it. It misleads when the token has moved into a second manifest in the same repo, so check every manifest, not only the root one.
- New token present. This proves the target stack is in use. On its own it misleads, because a greenfield repo has the new token without ever having had the old one.
- Holds for 90 days. This proves nobody reverted the migration. It misleads when the repo went quiet right after the change. A removal that held only because nobody committed again is weaker evidence than one that held through active development.
A repo with both tokens at HEAD (the latest commit on the default branch) has stalled. It has not finished. The common example is a hybrid ngUpgrade-style setup, where AngularJS and the new framework run side by side. The engineers on it may be excellent, but they have not yet done the part you are paying for: the cut-over, where the old framework is finally deleted.
The four layers of migration evidence
- Event logGH Archive dates the PR merge independently of the repo
- Merged pull requestShows who authored, reviewed, and merged the change
- Manifest diffShows the old token removed and the new token added
- HEAD plus 90 daysShows the removal held and was not reverted
Which search surfaces can see a completed migration
Commit search and merged-PR search are the only built-in GitHub surfaces that see history, so they are the ones that find finished migrations. Code search and package datasets can back up the evidence but cannot find it, so use each surface only for what it can do.
| Surface | What it can show | Limit that matters |
|---|---|---|
Merged-PR search (is:pr is:merged) | Who authored and reviewed the migration | 30 requests/min, authenticated |
| Commit search | Commits that name the migration | 30 requests/min, authenticated |
| Code search | New token present now | 10 requests/min, auth required |
| GH Archive (BigQuery) | Dated events, including merges | Events only, no file diffs |
| deps.dev | Dependency changes over time | Published packages only |
The GitHub REST search documentation sets the limits that shape your queries:
- Each search returns at most 1,000 results, at up to 100 per page.
- Each query searches up to 4,000 repositories that match your filters.
- A third-party code search tool documents a maximum query length of 256 characters and warns that GitHub may silently truncate full result sets.
Code search has a caveat I could not verify. It may index only the current default branch. If so, it can confirm the replacement is present but can never show that the old dependency was removed. You can check this yourself: take a repo you control where you removed a package months ago and code-search for that package name. If nothing comes back, treat code search as showing present state only.
The datasets date things. They do not prove anything. GH Archive's BigQuery copy updates every hour, has timeline data from 11 March 2012, and organises its tables by year, month, and day. It records events, not file diffs, so it can date a PR merge but cannot read the manifest. deps.dev covers Cargo, Go, Maven, npm, NuGet, PyPI, and RubyGems and lets you look back over time, but it only includes software published to those registries. Most migrations happen in unpublished applications, so deps.dev helps with library migrations, such as a library dropping Python 2 support, and not much else.
is:pr is:merged migrate webpack vite created:YYYY-MM-DD..YYYY-MM-DD is:pr is:merged "migrate to vite" created:YYYY-MM-DD..YYYY-MM-DD is:pr is:merged angularjs react migration created:YYYY-MM-DD..YYYY-MM-DD is:pr is:merged "remove angular" react created:YYYY-MM-DD..YYYY-MM-DD is:pr is:merged migrate ".NET Framework" ".NET 8" created:YYYY-MM-DD..YYYY-MM-DD "migrate to vite" committer-date:YYYY-MM-DD..YYYY-MM-DD
Swap in your tokens, then shrink the date window until each query returns fewer than 1,000 results.
The five-day procedure from migration pair to slate
Seven steps take one from-to pair to a graded, dated slate in about five working days. The order matters: confirm that a migration finished before you grade anyone who worked on it.
Migration pair to contract slate
- Fix the migration pair as manifest tokensWrite the exact package names to be removed and added, such as angular to react in package.json or webpack to vite, plus the source's end-of-support date. Hiring manager, half a day.
- Find candidate PRs and commitsSearch merged PRs and commits with migrate terms plus the token names, using created: date windows so each query stays under 1,000 results. Sourcer, one day, done at 30 to 100 candidate repos.
- Confirm completion from the manifestCompare the manifest before and after: old token gone, new token present, old token still absent for 90 days. Date the merge and cross-check it in GH Archive until 10 to 20 repos are confirmed.
- Attribute authorship in the migration rangeCalculate each author's share of commits and lines in the migration range, excluding bots, and list reviewers and approvers separately. Done when every confirmed repo has a share table.
- Grade each person Led, Contributed, or TouristApply the written thresholds from the grading section to every person, with the evidence link next to the grade. Engineering manager, half a day.
- Resolve identity and availabilityMatch each commit email or handle to a public profile, check freelance status, and flag anyone at an IT services firm. Sourcer, half a day to a day.
- Run the classification and budget checkWork through the ABC, IRS, and IR35 features and attach a rate band. Done when 3 to 8 names remain, each with a dated evidence link.
The time adds up to five to five and a half days. The work splits across three roles: the hiring manager owns the tokens, the sourcer owns search and confirmation, and an engineer or the engineering manager owns attribution and grading. Founders or legal take the last step.
How the candidate pool narrows
- 30 to 100Candidate repos
From merged-PR and commit search
- 10 to 20Confirmed completions
Manifest diff holds 90 days
- 3 to 8 peopleContract slate
Led or Contributed, cleared on rates and status
- 2 to 3Engaged
The engineers you actually contract
A few notes on the steps that tend to slip:
- Step 1 is the whole search key. If the tokens are vague ("frontend modernisation"), every later step gets noisy. Two columns of exact package names is the deliverable.
- Step 2 stops at 100 repos. More candidates do not buy more proof. If you are past 100, narrow the date window or add a second token, and don't read further down the list.
- Step 3 is where most candidates drop out. Expect hybrids, reverts, and greenfield repos. That is the funnel doing its job.
- Step 6 is the slowest manual step. Commit emails are often personal or no-reply addresses, and handles rarely match profile names. Refolk resolves this by connecting the public GitHub graph to the open web and LinkedIn in one plain-English ask, so this step doesn't need its own day.
Practitioners don't publicly disagree about this order. The one deviation I see is grading people before confirming completion, which spends a day on authorship tables for migrations that never finished.
How to grade Led, Contributed, or Tourist
Grade each person on two separate axes: their share of migration commits and their role in reviewing migration PRs. Write the thresholds down before you look at any names. The research supports scoring authorship and review separately, but nobody has published cut-offs for "led a migration", so the ones below are Refolk's own.
What the research supports
- Authorship can be measured per file. Avelino et al.'s truck-factor algorithm (ICPC 2016) identifies file experts with a Degree-of-Authorship (DOA) model. One implementation documents author thresholds of 0.75 and 3.293, tuned against git blame. The method was validated by surveying developers of 67 popular GitHub projects.
- Most repos are concentrated. The same line of work found that roughly two-thirds of 133 popular repositories had a truck factor of two or fewer. A truck factor is the number of people who would have to leave before a project stalls. For you, this means most migrations will have one or two dominant authors, which is why "Led" is usually findable.
- Review counts as expertise. JetBrains researchers extended bus-factor work to include code reviews, VCS data, and meetings data. That supports scoring review separately instead of ignoring it.
What the research does not settle
There is no published numeric threshold for "led a migration" that includes review or approval roles. DOA supports per-file expertise, not these grades. The thresholds below are working proposals: use them, write down every exception, and adjust them over time.
The cut-over PR is the pull request that removes the old token from the manifest. Authoring it is strong evidence on its own, because that is the change that commits the project to the new stack.
Repo: Migration commit range: <first migration commit> to <cut-over merge> Cut-over PR (removes old token): <link> merged <date> Person: <handle> Migration commits authored, bots excluded: __ of __ = __% Co-authored-by trailers credited: __ Migration PRs authored: __ Migration PRs reviewed or approved: __ Author of the cut-over PR: yes / no Led = 50% or more of migration commits, OR author of the cut-over PR Contributed = 10% to 49% of migration commits, OR reviewer on 3 or more migration PRs Tourist = below both Flag for interview: reviewed most migration PRs but authored under 10% Grade:
Fill one block per person per repo, and paste the evidence links before writing the grade.
Commit share against review role
How migration evidence goes wrong
Most bad slates come from eight failure modes, and each has its own check. Run every check before a name goes forward, because each one produces a convincing false positive.
1. The code-search false positive
The repo has the new dependency but never had the old one, or still has both. A hybrid ngUpgrade-style setup has stalled. It has not finished. Check: confirm in the manifest diff that the old token is gone at HEAD and stays gone for 90 days.
2. Blindness from the result cap
Broad queries hit the 1,000-result cap, and GitHub may truncate them silently. The repos you never see are not random: they are whatever fell past the cutoff. Check: split queries into created: date windows until each one returns fewer than 1,000 results.
3. Attribution after a squash merge
One maintainer merges everyone's work, so commit share makes the merger look like the lead. This is the most common way a Led grade goes to the wrong person.
4. Inflation from bots and codemods
Renovate and Dependabot commits, or a single automated codemod commit, inflate line share. Check: exclude bot accounts and weight by PR count rather than lines. AI-generated code adds a related problem: line-based authorship measures rest on a single inference, that authoring code means understanding it. When a large share of the diff looks generated, use the first call to test understanding instead of trusting the share.
5. Leads who only reviewed
Senior people who approved every PR but wrote little code get graded Tourist if commit share is the only measure. Check: score review role separately. The Contributed threshold of 3 or more reviewed migration PRs exists for this case.
6. The profile-keyword trap
Only 10 US profiles in Refolk's index list Webpack, Vite, and "migration" together. Keyword search misses people whose proof lives in their repos, and it pulls in people who claim both stacks without finishing anything. Check: never let a profile keyword stand in for a dated diff.
7. Consultancy employees
You may not be able to engage these people directly. Check: look at the terms of their current employment before you contact them, and be ready to go through the firm instead.
8. Misclassification
A signed contractor agreement does not settle worker status. Under California's ABC test, the courts and the Labor Commissioner will ignore the contract and apply the test. Check: run the classification step before you make an offer, not after.
Rates, classification, and first contact
Price the engagement against published contract medians, check classification before the offer, and open the first message with the evidence you found. Rate data for migration contractors specifically is not published, so you are pricing from a nearby benchmark.
Rate benchmarks
ITJobsWatch publishes UK medians from advertised contract rates:
| Tag / region | Median £/day | Period ending | Quoted rates |
|---|---|---|---|
| React, UK | 500 | 18 Jan 2026 | 673 |
| React, England | 515 | 14 Dec 2025 | 593 |
| React, Midlands | 472 | 1 Oct 2026 | 52 |
| React Native, UK | 425 | 14 Jan 2026 | 63 |
| IT Consultant, UK | 550 | 28 May 2026 | not shown |
Limits to keep in mind:
- These are medians of advertised rates over rolling six-month windows, and the periods do not line up across rows. Re-check the live page before you quote a number.
- I could not find a published rate survey specific to migration contractors, or a US government source for contractor day rates. For US engagements, you need your own benchmark.
- The title changes the price. The UK React median fell from £550 to £500 between periods, while IT Consultant sits at £550. A role advertised as "migration consultant" may price above one advertised as "React contractor". This is an inference from two tags, not a measured premium.
Classification features to check
California's ABC test sits in Labor Code § 2775, enacted by AB5 and codified effective 1 January 2020. The hiring entity has to prove all three of:
- The worker is free from its control and direction.
- The work is outside the usual course of the hiring entity's business.
- The worker has an independently established trade or business.
The test covers any work performed in California, wherever your company is based. Two features of a migration engagement matter most:
- An end date helps. A continuous relationship with no reasonably planned or estimated end points toward control. Write the deliverable (the old token out of the manifest) and an end date into the agreement.
- Core product work fails Prong B. If the migration is your product, the second prong is hard to meet. Take legal advice before you choose between a contract and a fixed-term hire.
I have not re-verified the IRS common-law test (behavioral, financial, relationship) or the UK IR35 off-payroll rules here. Read the IRS independent contractor guidance and the GOV.UK off-payroll working guidance directly for engagements outside California.
Subject: Your <old> to <new> migration in <repo> Hi <name>, I found the cut-over PR you authored in <repo> (<PR link>, merged <date>). It removed <old token> from <manifest>, and it has stayed out since. I have the same migration to run: <one line on codebase size and shape>, in a fixed window of <weeks>, ending <date>. I am looking for someone who has done the cut-over before, on a contract basis. Would you be open to a short call this week to talk through how yours went? If you are not taking contract work, a pointer to anyone else who worked on that migration would help just as much. <your name, role, company>
Replace the bracketed parts with the repo, PR, and dates from your evidence file, and keep it short.
The last line of the message matters. Migrations have one or two dominant authors, and the Led person often knows exactly which Contributed engineer handled the hard parts.
Keeping the slate current
Re-run the search for each new migration pair and refresh a standing slate before you reuse it. New completions keep appearing in public repos, and nobody has published how the pool changes with time since end-of-support.
| Source | End of life | Months since EOL at 2 Nov 2026 |
|---|---|---|
| AngularJS | 31 Dec 2021 | 58 |
| Vue 2 | 31 Dec 2023 | 34 |
| Python 2 / CentOS 7 / .NET Fx 4.x / webpack 4 | not verified here | n/a |
AngularJS was deprecated after a long-term support period on its final version, 1.8.3. Vue 2's final release is 2.7.16. For the unverified rows, check endoflife.date, python.org, and Microsoft's lifecycle pages, and record the date you checked. To recompute the months column, count from the EOL date to today.
Demand for older pairs does not disappear when support ends. One commercial support vendor estimates AngularJS still powers over 1.2 million live websites. Treat that as a vendor figure, but it is a reason to keep an AngularJS-to-React slate warm instead of rebuilding it from scratch.
To keep a slate usable:
- Re-check the 90-day hold on each person's evidence repo. A later revert or a reintroduced old token downgrades the evidence.
- Re-date anything you rely on against GH Archive. It updates hourly, so new merges are quick to confirm.
- Refresh the rate band from the live median pages before every offer, because the six-month windows move.
- Re-grade when you find new evidence. A Contributed engineer who has since led a second migration moves up.
Before you call the slate done
- Every name has a link to the commit or PR where the old token left the manifest, with a merge date.
- The old token is absent at HEAD in every evidence repo and has stayed absent for at least 90 days.
- No evidence repo still contains both the old and new tokens.
- Every search query returned fewer than 1,000 results, or was split into date windows until it did.
- Bot accounts and single codemod commits are excluded from every share table.
- Squash-merged PRs are credited to the PR author and co-authors, not the merger.
- Review roles are scored separately from commit share for every person.
- Each person carries a Led, Contributed, or Tourist grade with the threshold that produced it.
- Anyone at an IT services firm is flagged, with their current employer's terms checked.
- Each engagement has a written end date, a classification review, and a rate band from a dated median.
- The slate holds 3 to 8 names.
Questions practitioners ask
How do I vet a migration consultant who says they have done this migration before?
Ask for the cut-over pull request, meaning the one that removed the old dependency from the manifest. Then check three things yourself: the old package is gone at HEAD, it has stayed gone for 90 days, and the person authored that PR or wrote a large share of the migration commits. References and case studies tell you a project happened. A dated diff tells you this person did the cut-over.
Can I just search LinkedIn for people who list AngularJS and React?
You can, but it gives you volume without proof. In Refolk's index, 412 US profiles list AngularJS, React, and "migration" together, and nothing in that count separates the person who led a cut-over from someone who maintained a half-migrated hybrid. For newer pairs it fails outright: only 10 US profiles list Webpack, Vite, and "migration". Start from repo history and use profiles only to find a contact route.
What if the best candidate did their migration in a private repository?
This method only finds public evidence, so private work never shows up in the search. If someone claims a private migration, keep them on a separate unverified list. Ask them to walk you through the token list, the cut-over sequence, and what broke after the switch, and check with a reference who saw the work. Do not give them a grade on the same scale as people with dated public diffs.
How do I tell who led a migration when the PRs were squash-merged?
Read the PR author field and the co-authored-by trailers, not the committer. When a maintainer squash-merges everyone's work, the merged commit often carries the maintainer's name, so commit share makes the merger look like the lead. Credit the PR author, give trailer credit to co-authors, and leave out merge-only activity before you apply the Led threshold.
Can I hire a contractor for a core-product migration in California?
Possibly, but the contract alone will not protect you. California's ABC test, in Labor Code section 2775, applies to any work performed in California. The hiring entity has to prove all three prongs. Prong B usually fails when the migration is core product work, and an open-ended engagement with no planned end points toward control. Get legal review before you make the offer.
How long does it take to build a migration contractor slate this way?
About five working days. That is half a day to fix the tokens, one day to find candidates, one day to confirm completions, one day to attribute authorship, half a day to grade, half a day to a day to resolve identities, and half a day for classification and rates. Expect 30 to 100 candidate repos to narrow to 10 to 20 confirmed ones and then to a slate of 3 to 8 people.
Try it on the search you came here for
Stop building boolean strings. Just describe the person.
Type one sentence. I plan the search, read GitHub, public LinkedIn and Crunchbase records, and the open web as it is right now, and hand back a ranked list with the reason next to every name.
01Describe them
One plain sentence. Role, city, stack, stage, whatever matters to you.
02I read the web live
GitHub, public LinkedIn and Crunchbase records, the open web. Not a database that went stale last quarter.
03You read the shortlist
Ranked, with the reasoning under every name. Open a profile, ask a follow-up, narrow it down.
- Staff backend engineers in NYC who shipped Rust in production
- Series A fintechs in SF under 50 people, growing headcount this year
- Maintainers of fast-growing Rust web frameworks on GitHub
- No boolean, no filters, no seat to buy. One box.
- Read at search time, so a profile updated yesterday counts today.
- Every step visible as it runs, every name with its reason.
500 free credits on sign-up. No card, no demo call. See real searches.