> scary rebase -i commands that can leave your tree in a half-broken state if you so much as sneeze
`git rebase --abort` exists. One can also set a tag or something before doing the rebase, do whatever, then `git reset --hard $set_tag` to go back. Nothing to be scared of. Not like the prior state is lost.
I have so many branches named `temp` or `before-rebase` for exactly that reason; I'm using them effectively as tags, but branches can be moved around with less ceremony than tags (since tags are designed to be for things like v1.2.3, placed once and then almost never moved again), so I usually just do `git branch before-rebase/some-feature` before running a big `rebase -i`.
I've almost never needed to run `get reset before-rebase`. But I have often done `git log -p before-rebase` and compared that to the post-rebase state of the branch, to ensure that the merge-conflict resolution(s) that came up during the rebase haven't accidentally introduced an unintended change.
Seconded, I diff diffs all the time after a rebase or after merging the `develop` branch into my feature branch (which I sometimes do when the rebase would have produced so many merge conflicts over so many commits that it's just not worth the hassle, even using rerere — and since our team routinely uses the GitHub "Squash and merge" button, the develop->feature branch merge gets squashed away and doesn't end up showing up in the develop branch log once the PR is merged). It's the best way I've found to double-check that I didn't made a mistake in merge conflict resolution: does the diff from branchpoint to before-rebase still match the diff from new branchpoint to after-rebase? Yes? Then I probably didn't screw up the merge conflict resolution.
> but branches can be moved around with less ceremony than tags
`git tag -f` to move a tag.
Personally, I just do `git show` when I'm feeling cautious, but I can generally just scroll up to find the last `git commit` I did with the hash in the output. `git reflog` should also have record of it, so everything else is kind of extra.
Good point, that's no more ceremony than moving a branch. I guess I've just gotten "branches are movable tags" so deep into my hindbrain that I absorbed "tags are hard to move". But that's not actually true, and for what I'm doing (save this point in history for a while) a tag makes slightly more sense, semantically, than a branch.
git tags are more lightweight than they seem. It's why the UX defaults to not sharing tags, with the idea that you may need/want local-only tags. They also share the same "namespace" that you could have tags like `myname/some-personal-tag`. (I've used `project-name/v1.2.3` style tags in monorepos rather than solitary versioning the entire repo.)
`git tag -d` deletes tags and `git tag -f` moves them (forces them to change).
For the most part whether you prefer a branch or a tag for temporary marks is an aesthetic choice, though the twist is maybe using annotated tags. The annotated tag allows you to leave a commit message for yourself why you made the temporary tag in a way that you can review later. Just like optionally adding a stash message (which also reflects why stashes work under the hood more like tags than like branches).
The fact that I misread that as "prebase" (I've done the same misreading with "prerelease" in the past, too) is why I prefer `before-rebase`, even though `pre-rebase` is slightly faster to type.
The branch reflog (git reflog <branchname> or git log -g <branchname>) is a lot easier to follow in the case of rebase than the HEAD reflog (which gets an entry for each commit that gets checked out / applied).
`git rebase --abort` exists. One can also set a tag or something before doing the rebase, do whatever, then `git reset --hard $set_tag` to go back. Nothing to be scared of. Not like the prior state is lost.