A few weeks ago I was staring at a table in a database, trying to figure out when a column showed up and why a particular foreign key existed. The answer was in there somewhere, spread across thirty-odd migration files, and finding it meant opening them one by one. EF Core migrations are great at telling you what changed — one file, one point in time. They're not great at telling you how something evolved.
So I built a small tool to fix that for myself: ef-timelapse. It replays your EF Core schema history — either from migration files, or from Git history if you're on a scaffolded/database-first setup with no migrations at all — into one browser-based timeline you can scrub through, search, and diff.
dotnet tool install -g ef-timelapse
ef-timelapse serve C:\Path\To\YourProject
That's really the whole setup. It figures out on its own whether your project uses migrations or is a scaffolded project tracked in Git, and serves the same interactive viewer either way.
Two ways to look at schema history
If you've got a Migrations folder, migration mode parses every file with Roslyn and replays each migrationBuilder call in order. You get a slider that walks through every migration, showing exactly which tables and columns it touched at each step:
If you don't — a lot of database-first projects scaffold their model classes straight from an existing database and never touch migrations — Git scaffold history mode walks your Git history instead and replays how the generated model files changed commit by commit. Same idea, different source of truth.
Both modes drop you into the same viewer. Same slider, same search box, same detail panels — just backed by different data underneath.
Finding when something actually changed
The feature I built for myself and now use the most is the per-entity (or per-table, in migration mode) history panel. Instead of clicking through commits one at a time hoping to spot when a property got added, you search for the class or table by name and get every point in history it changed, newest first:
Same thing works for tables and columns in migration mode — search "Orders" and see every migration that touched it, in one place, instead of opening files one by one:
It shows you the actual diff, not just a summary
In Git mode, clicking a changed file at any commit shows the real inline diff — added and removed lines highlighted — not just "+12 -3" and nothing else:
Does it hold up on a real codebase?
I didn't want to just demo this against a toy project with five commits, so I pointed it at eShopOnWeb, Microsoft's reference ASP.NET Core + EF Core sample app — 455 real commits, real entities, real migrations. Every screenshot in this post is from that run. The first time you point Git mode at a repository like that, it has to walk the full history and index it, so you'll see a progress modal while that happens:
After that first pass it's cached on disk, so running it again against the same repo starts instantly. If you're actively working on the project, --watch picks up file changes live too.
What it deliberately doesn't do
I'd rather it tell me "I don't know" than guess wrong. If a migration operation depends on something the parser can't statically resolve — a local variable, a helper method call, raw SQL, a branch in the code — it gets reported as an unsupported step with the exact source line, instead of being silently skipped or guessed at. It also only replays the forward path (Up()); rollback history isn't visualized. This is a read-only exploration tool, not a migration generator.
Try it
dotnet tool install -g ef-timelapse
ef-timelapse serve <path-to-your-project>
It's open source, MIT-licensed: github.com/xonaib/ef-timelapse. If you run it against your own project and it chokes on a migration pattern or gets a schema shape wrong, I'd genuinely like to hear about it — open an issue, or a PR if you've already got a fix in mind.






Top comments (0)