`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.
$ git log --oneline --show-signature # look ma, I signed my commits!
3a1dd8f gpg: Signature made Mon 13 Jul 2026 10:45:50 PM CDT
gpg: using RSA key FBF32CDBCC134B44FD29B66FA851D929D52FB93F
gpg: issuer "chandler@chandlerswift.com"
gpg: Good signature from "Chandler Swift <chandler@chandlerswift.com>" [ultimate]
Second commit
03c3f6e gpg: Signature made Mon 13 Jul 2026 10:45:16 PM CDT
gpg: using RSA key FBF32CDBCC134B44FD29B66FA851D929D52FB93F
gpg: issuer "chandler@chandlerswift.com"
gpg: Good signature from "Chandler Swift <chandler@chandlerswift.com>" [ultimate]
Initial commit
$ git history reword HEAD~
$ git log --oneline --show-signature # oops! where'd they go?
5662b2c (HEAD -> main) Second commit
6bf6830 Initial commit amended
This has pushed me back to the time-honored `git rebase -i` since I do want to keep my commits signed.I'm convinced that a big part of people often finding Git and rebase difficult is a user interface issue, having to know all the correct command line options and having to make your own mental model of what's happening and what you want to do, all makes it difficult to get a firm grasp on things.
I can't comment on what equivalent alternatives (especially on macOS/Linux as I'm a Windows user), but in terms of a UI for Git which exposes enormous power in an easy-to-use way I've found TortoiseGit to be spectacular and I especially like its rebase dialog:
https://tortoisegit.org/docs/tortoisegit/tgit-dug-rebase.htm...
Which you kick off from a context menu option from the commit line on the commit log you want to rebase onto with a simply named "Rebase <current reference> onto this" option:
https://tortoisegit.org/docs/tortoisegit/tgit-dug-showlog.ht...
It's super easy to re-order, split, combine, edit commits from here and it's obvious that will happen. If for whatever reason you decide you want to back out midway, you just abort and you're back to where you were.
I will concede there are aspects of a TortoiseGit I find a bit annoying, particularly that I feel I have to click around too much, instead of a shell extension I would prefer an app you launch with tabs or something, but I think this is a fundamental design principle of TortoiseGit, which followed the same principle as TortoiseSVN.
There is Git Extensions for Windows which seems nice at a glance, I tried it briefly, but I think I didn't stick with it either due to being unable to find an option I regularly used or I was just so used to TortoiseGit already.
Simplifying `git rebase -i` is a great idea, but unfortunately, that does not match my workflow.
I always keep an history of my branches. For example, when I develop a feature, the first version of the branch is `myfeature.1`, then `myfeature.2`, and so on. This is useful because I can retrieve an old version when something behaves differently in a newer one. (And no, `git reflog` will not help)
This has saved me multiple times. For example, I can determine that a problem was introduced between `myfeature.58` and `myfeature.59`. If the "feature" contains 15 commits, I do:
git range-diff myfeature.58~15..myfeature.58 myfeature.59~15..myfeature.59
This lets me see the changes between the 2 versions, commit by commit (even if they don't have the same base).I don't want all the branches containing a commit to be rebased automatically (I already try using tags for old versions instead, but this does not quite fit).
If you can give `jj` a try on a greenfield, single-developer project, you probably should. It feels exactly like Git felt compared to Subversion (when you focus on JJ's strengths and use it in favorable conditions - it is young, after all). Get acquainted with `jj` on its terms, and if things click for you, you'll be a bit better prepared for the bumpy road that is Git interop later on.
I'm reading that to mean that when I use `git rebase --update-refs` in this situation, where I've currently checked out `D` and update `B` to `B'`:
A ──► B ──► C ──► D
│
└───► E
I'll end up with this state, where `E` remains untouched? A ──► B' ─► C' ─► D'
│
└───► B ──► E
(EDIT: Originally I had `E` point to `B'`, which doesn't make sense)If I use `git history fixup`, it would also update `E` and end up with this?
A ──► B' ─► C' ─► D'
│
└───► E'
If that's the case, is there a way to get `git rebase` to have the same behavior? I've got decades of `git rebase` burned into my fingers at this point.That's not really trying, let's assume you need 1 week to change ingrained workflows, so you just waste time every 3 months stopping right before the threshold. Better try once every year, but for a few*4 days...
Complete bullshit. Might as well say "scary screwdriver that can turn up in your recturm if you so much as sneeze". Sure, I believe that might have happened to you (heard stories from friends that work in the emergency room), but I run rebase -i 10 times during the time I work on each branch (literally: I don't even care to write "proper" commit messages while writing the code, will reorganize and clean them up later anyway), and it never happened to me.
I'm glad to hear it, I thought that was just me. It gets especially hairy when moving commits around...
Plus I have 3-way diffs enabled and I usually get confused by which section is which at least once a day.
Also: does anyone know if `magit` has history support?
What happens with a conflicting fix though? Do I still need to resolve all conflicts on the base branch and `reset --hard` all other branches?
It sounds like there was probably an equivalent using an existing command but this is easier for me to understand. Thanks for sharing!
somewhat related Q:
how do you give two files the same ancestor? so git log will for each show the history to the beginnings of the originally unsplit file? useful for splitting large files.
BTW I have made a notion doc on git commands: https://rushilpatel.notion.site/git
This regression was caused in <hash> on December 19, 2017.
The fixup and rewrite of history has to ferret out these has references and fix
them to the new hash of the same commit.I have scripted this before!
I mean, just use stgit[1] to maintain a stack of patches instead of parallel branches, it's so much better. You can easily wrangle thousands of patches (aka commits) with stgit.
A lot of people, on first encountering stgit, read a bit about it, think "why do I need this? I can do the same thing with just plain ol' git.". Yeah, you can. But not at scale. Not practically. Not with thousands of commits. And it makes the case when you just have a few tens of commits absolutely trivial. Try it for awhile and you'll find it indispensible.
I think that only happens when you work on code as text files (i.e character streams) instead of code (i.e structured content with meaning). Like you have commit A and commit B that is in conflict, you should be glad because that's a rough signal that the intent of A and B differs. Your goal should be to think about how to compose A and B so that both intent survives (unless one supersedes the other). Which means you should be at least familiar with A and B.
The issue I found with people that fears conflict is that they often don't understand either A or B (or both). So they are a bad candidate to actually do the operation. It's not a matter of git's cli interface, it's a matter of codebase comprehension and how well you're familiar with the changes in question.