I mean, that's option 2 of what you're quoting, and is generally my preferred option. That said, there are cases where it breaks down and I end up wanting worktrees or independent clones, generally involving ≈`.gitignore`d local data:
• A newly created bugfixing branch may take awhile (minutes? hours?) for me to build. I can either go on a coffee break while waiting for it (since I can't very well test my ability to reproduce the bug, nor verify my bugfixes work, without having said branch in a compiling state), or I can have said build occur in a secondary worktree - and continue working on my original task in my primary worktree while waiting for it to build.
• If I've got a lot of `.gitignore`d config file tweaks related to my major feature work / profiling / debugging / ???, I might not want to bring those over to my bugfixing session. `git stash push --all` is an option, but that will get build artifacts - which will take awhile to stash - not just my local config files. A fun ancedote: I once wasted an hour failing to reproduce a game's audio crash because a local `user.ini` file had the entire audio system disabled via feature flag. (I now prefer setting the volume to 0 instead.)
• I do a bunch of porting and cross-platform abstraction stuff, which makes my build times even worse than usual by having to repeat builds N times. I might not want to invalidate by main build cache for all that, when my bugfixing branch might only reasonably need local testing on 1 platform, and gain next to no benefit from the previous cache as is (depending on how far diverged the branch I was working from and the branch where the bugfix should occur are.)