in my opinion your staging/production parity needs to be really good if you do large iterations in prod, deploying smaller changes constantly will get you little oops moments more often, but you'll be able to fix them immediately since it's clear what caused it, as opposed as 2+ weeks of commits going to prod at once.
we had every feature branch create its own little minimal staging environment and started bugging developers to finish up after a week (the staging environment would tear itself down if not told to stay up explicitly via PR labels). and those feature environments went straight into main/production.
Or only require code owner approval on staging->master (or only requiring code owner approval on merging to staging)
I’m sure there are ways to accomplish the same sort of thing with tags, I’m not hugely tied to this workflow (other than it seems to work for our team)
People that do trunk-based development would consider 2-3 weeks as quite long. My definition of short-lived is about 1 day.
I’m guessing with a 1 day PR length, you’re mostly pushing finished code ready for peer review.
master branch - code currently deployed to production. never used as the base branch except rare hot fixes
staging branch - the base branch for all feature branches. On prod deploy, staging is merged to master with a merge commit (probably could (should?) be a rebase)
feature branches - always use staging as base branch
Most critically: all feature branches are squashed and merged, so that each single commit in master corresponds to a single PR.
Makes it easy to revert PR but difficult to cherry pick after squashing. Also keeps the hit history extremely clean and condensed. Not sure if this method will scale, but it’s working well at our company with 6 engineers with 20 or so feature branches open at any given time.
Edit: one reason this works for us is we keep feature branches short-lived (ideally at most 2-3 weeks) and staging gets merged to master twice a week (we do a deploy Mondays and Thursdays)