hollyhook, I like your strategy of "commit early, commit often". I've been doing it similarly. At each "feature" I introduce to my patch I commit - with a feature being the tiniest thing you can describe your patch doing.
phil: do you use any special tricks to help? I send this message to max with a loadbang:
;
max sortpatcherdictonsave 1
as I saw suggested in a post here from several years ago. Which keeps the patcher sorted the same and reduces differences, if you do any merging.
I also have been abstracting out parts more - so that each section of my main patch is it's own maxpat file. The idea is that smaller, separate patches will make it easier to merge when I go on to doing that. I don't know if that will be true... But at least my main patcher is cleaner!
I'd be interested in trying to write a diff program that would ignore certain parts of the .maxpat text - such as cord positioning - and instead just check for what objects are included, what is connected to what else, and only things that actually make a difference in the patch we see.