If looking at a source browser of a previous version of your code is not adequate to understanding how it worked, such that you wish to "rewind" to that version and run it, then your code is very poorly written.
It is indeed difficult sometimes to understand our own code some time after it is written, but by following good practices (ideally functional, with mostly pure functions), it should be readable.
I will venture a (biased) guess that one of the biggest challenges to understanding the code was the mutation of objects in the process. This is the #1 reason why functional programming is superior. With FP, you can grok what a function does and then comfortably forget about how it does it. It takes input, it produces output. Period. As long as you agree with the transformation algorithm, you can reduce that complexity to a one-line description.
Even in non-FP-first languages, you can usually write pure functions. Some scenarios have enough performance demands that you must mutate things, but probably most situations can be approached with FP styling.
All this rewinding and undoing is a distraction from the real problem. The real problem is that "it smells". It smells like a level of complexity that should not be.
In my 30 years of professional programming, and even with my admittedly declining short term memory, I have never felt lost without access to versions of code from 5-15 minutes ago.
Not to be harsh, but I really think that this indicates some fundamental approach issue rather than a tooling problem.
If it cannot be written on paper (or tablet note with pen) as rough pseudocode... or even drawing boxes and arrows for the visually-inclined, then the problem is not understood. Take what is understood and codify it, pushing the complexity and the unknowns to the edges. At least that reduces the complexity.
One aid I do lean on heavily though is a REPL. Load the code and do some interactive work with it. Inspect the data, test some transformations, and then write code to do what works. That's my current approach to situations that I cannot immediately and accurately write in one pass.
> One aid I do lean on heavily though is a REPL. Load the code and do some interactive work with it. Inspect the data, test some transformations, and then write code to do what works. That's my current approach to situations that I cannot immediately and accurately write in one pass.
Honestly, this sounds mostly like what you're chastising, except you're doing it outside of the main workflow.
(Ok, looking at your profile and your background, I must be missing something. You surely don't need 5 or 10 minute history of code to know what you are doing.) Please help me understand what I am missing from this conversation!
You know what? Most of these ‘disagreements’ about coding workflow and tool choice in which one person is telling another person that they’re Doing It Wrong boil down to different strokes for different folks.
This seems to be a fine example of that.
(Though I must admit that consternation about how often someone presses Ctrl-Z is a bit lower level than I’m used to seeing.)
A common example from my work: I’m doing layout code, so I need to clean up some constraints that are broken. Often this a fairly manual process where I change some code and run it to see how it does, and then adjust the code as needed. Sometimes I need to change my strategy (instead of manually pinning this view, I can put it in a stack view…) and this requires me to change a couple lines of code. Then I run it and it breaks in a way that makes me realize that this direction was a dead end, so now I want to go back to where I was five minutes ago. Or, sometimes this is the way I wanted to go but in the process of rewriting it I forgot to carry over a constraint, so I want to see how I was doing it before and pull out a line or two so I can include it in the new code.
It is indeed difficult sometimes to understand our own code some time after it is written, but by following good practices (ideally functional, with mostly pure functions), it should be readable.
I will venture a (biased) guess that one of the biggest challenges to understanding the code was the mutation of objects in the process. This is the #1 reason why functional programming is superior. With FP, you can grok what a function does and then comfortably forget about how it does it. It takes input, it produces output. Period. As long as you agree with the transformation algorithm, you can reduce that complexity to a one-line description.
Even in non-FP-first languages, you can usually write pure functions. Some scenarios have enough performance demands that you must mutate things, but probably most situations can be approached with FP styling.
All this rewinding and undoing is a distraction from the real problem. The real problem is that "it smells". It smells like a level of complexity that should not be.