By default, you can select any block of text and the undo command will cycle through the changes only from that region of your buffer.
does it understand syntax boundaries like curly braces / functions? ('undo within function' would be key). or just line #?
For eg, see https://www.johndcook.com/blog/2017/08/09/selecting-things-i...
Another vanilla feature I sometimes use to keep track of old code is the "kill ring". Just cut the old code and it will be available in there later if needed.
By default, Emacs has a linear undo structure, while still allowing you to never lose history.
The undo-tree terrifies me.
The source for undo-tree contains documentation which very effectively describes the way the library works with examples and comparisons with how Emacs does things by default: https://gitlab.com/tsc25/undo-tree/-/blob/master/undo-tree.e...
More generally, for anyone new to Emacs and struggling as I once did, I can't recommend strongly enough that you learn how to use the help system (C-h C-h) and the built-in manual (M-x info). Emacs can teach you a great deal about itself, and these are the ways it does so.
EDIT: Or are you programming in APL?