Local History in Rider: undo and redo on steroids
We’ve all been there. Investigating a bug, making some code changes, then finding that these changes don’t fix the bug. Rinse, repeat, and two hours later we realize that first attempt needed just a little tweak. How can we roll back to it if we did not commit it to Git or Mercurial? How can we roll back any change we made to the code base between source control commits? Undo only goes so far…
In JetBrains Rider, there’s a solution to that: Local History. It’s a real-time, local version control that keeps track of changes we make to our code base.
What is Local History?
When we’re “in the flow”, our project and source code constantly changes. We write, refactor and debug, and when we finish a task, code is committed to a version control system (VCS) like Git or Mercurial.
Unfortunately, commits to the VCS are just snapshots. If we’re lucky, changes in between commits are captured in the undo stack, but that disappears if we close the IDE and reopen it a later time. Undo also does not track external changes, made outside of the IDE. What’s even worse: don’t you hate it when you undo 20 times, then accidentally press the keyboard so you can’t redo anymore?
This is where Rider’s Local History comes in: it keeps track of source code changes and file changes in our project in between VCS commits. Whenever something changes (and is persisted to disk), local history tracks the change and allows us to roll back (or forward). Accidentally deleted a folder of files that weren’t yet committed? Want to get back that class or entire namespace you wrote on the train commute home from work, was dropped a few minutes ago and never committed to source control? Local History!
Local History is enabled by default and keeps track of all every save (or delete), whether explicit (Ctrl+S) or implicit (Rider auto-saves every few seconds). It tracks changes in a solution or project, folders within our solution, files, classes, … As long as the file is text-based, Local History has it covered.
Showing Local History
One place where we can view local history is under the VCS | Local History | Show History menu. It will bring up a diff viewer where we can see a list of changes made to the file we have open. On the left, we can see a description of the changes. On the right, a diff between the current and previous version is shown.
Just like in a regular diff/merge view, we can restore lines and blocks of code, or roll back to a previous version of the file. Doing so will update the file that is open in the editor, or in the case of e.g. a solution folder, files can be restored.
It’s also possible to label a specific point in time, for example right before we start a massive refactoring effort. Labels can be added using the VCS | Local History | Put label menu, and are shown in the Local History change list as well. Note that labels are solution-wide and apply to all files and folders.
What with external changes? Local History tracks those, too. For example, here I dropped the folder Consent outside Rider. Invoking Local History on the parent folder shows us that an external change was detected and we can revert from here if we want to.
There are a couple of entry points to Local History:
- The Local History context menu in the Solution Explorer or in the editor (tip: selecting code will show Local History for just the selection)
- The VCS | Local History menu
- The VCS operations popup (Ctrl+Alt+Q)
Another entry point is the View | Recent Changes popup (tip: map it to a keyboard shortcut). It shows us a list of recent changes in our solution and lets us quickly open up Local History to view more details.
Cleaning Local History
While having Local History is a real life saver sometimes, its internal database may grow over time. Local History is cleaned when installing a new version of Rider, or when invalidating caches using the File | Invalidate Caches menu.
Keep in mind that Local History really is local. The history is stored locally and not shared with other developers working on the same project. Make sure to keep using proper source control as well!
Download the latest Rider EAP build and experience local history in action! Your feedback is appreciated.
Subscribe to Blog updates
Thanks, we've got you!
Visualize Entity Framework Relationships and Additional Query Analysis in ReSharper 2023.3
A lot of teams are using Entity Framework or EF Core to work with their database. As an Object-Relational Mapper (ORM), it bridges objects in code to a relational database model, so that as a developer you don’t have to worry too much about the actual database. We all know: that’s not entirely tr…
Automatically Analyze ASP.NET Core Performance With Dynamic Program Analysis
Slow web pages may make your users or customers abandon your web application, even before they’ve had a proper look at it. You’ve likely also been frustrated working with a web application that is slow to load. The good news is that the latest versions of ReSharper and JetBrains Rider’s Dynamic P…
OSS Power-Ups: MassTransit – Webinar Recording
The recording of our webinar, OSS Power-Ups: MassTransit, with Chris Patterson, is available. This was the thirteenth episode of our OSS Power-Ups series, where we put a spotlight on open-source .NET projects. Subscribe to our community newsletter to receive notifications about future webinars.…
Eager, Lazy and Explicit Loading with Entity Framework Core
Entity Framework Core (EF Core) supports a number of ways to load related data. There’s eager loading, lazy loading, and explicit loading. Each of these approaches have their own advantages and drawbacks. In this post, let’s have a quick look at each of these ways to load data for navigational prope…