{"thread":{"id":"66391","subject":"[BUG] git-history in the middle of rebase leads to a broken state","startedAt":"2026-09-25T14:13:02Z","lastAt":"2026-09-25T14:13:02Z","messageCount":1,"participants":["Nikita Bobko"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"553283","messageId":"1a0d8e97d66.360c5b64612300.827632721379389681@nbobko.com","threadId":"66391","inReplyTo":null,"subject":"[BUG] git-history in the middle of rebase leads to a broken state","fromName":"Nikita Bobko","fromEmail":"nikita@nbobko.com","sentAt":"2026-09-25T14:12:55Z","receivedAt":"2026-09-25T14:13:02Z","isPatch":false,"body":"git-history by default updates all branches that are descendants of the\noriginal commit to point to the rewritten commit. That also includes the\nbranch that is *currently being rebased* (if such a branch exists),\nwhich leads to a broken state. Even `git branch --force` doesn't allow\nchanging the currently being rebased branch.\n\nI'm cc'ing Patrick Steinhardt, the original author of the git-history\ncommand -- I hope that's fine.\n\nI searched the mailing list and, to my knowledge, these types of bugs\nhaven't been reported yet (feature interactions between git-history and\ngit-rebase/git-cherry-pick).\n\n## Full reproducer\n\n    $ git init # CMD_1\n    Initialized empty Git repository in /Users/bobko/git-history-bug/.git/\n\n    $ bash -c 'for i in 1 2 3 4 5; do echo $i > $i.txt; git add .; git commit -m $i; done' # CMD_2: Populate git history\n    [main (root-commit) edff563] 1\n     1 file changed, 1 insertion(+)\n     create mode 100644 1.txt\n    [main 106a0da] 2\n     1 file changed, 1 insertion(+)\n     create mode 100644 2.txt\n    [main a36b6d5] 3\n     1 file changed, 1 insertion(+)\n     create mode 100644 3.txt\n    [main fd8f39c] 4\n     1 file changed, 1 insertion(+)\n     create mode 100644 4.txt\n    [main e641e3f] 5\n     1 file changed, 1 insertion(+)\n     create mode 100644 5.txt\n\n    $ git log --oneline # CMD_3\n    e641e3f (HEAD -> main) 5\n    fd8f39c 4\n    a36b6d5 3\n    106a0da 2\n    edff563 1\n\n    $ GIT_SEQUENCE_EDITOR='perl -i -pe '\\''print \"break\\n\" if $. == 1'\\''' git rebase -i a36b6d5 # CMD_4: Prepend 'break'. Stop the rebase\n    Stopped at a36b6d5 (3)\n\n    $ git log --oneline # CMD_5\n    a36b6d5 (HEAD) 3\n    106a0da 2\n    edff563 1\n\n    $ git log --oneline -1 main # CMD_6: main still points to the original commit - good\n    e641e3f (main) 5\n\n    $ echo 3 > 2.txt && git add . && git history fixup HEAD~ # CMD_7: The command that breaks everything\n\n    $ git log --oneline -1 main # CMD_8: Oops, main has been overwritten by git-history - bad\n    24fe5b2 (main) 5\n\n    $ git rebase --continue # CMD_9: Now, git-rebase is broken\n    error: update_ref failed for ref 'refs/heads/main': cannot lock ref 'refs/heads/main': is at 24fe5b2e2c697c43bc77fde0cfd25022cf5eadba but expected e641e3f7f50d0c07650e47b31c8198d57d5598db\n    error: could not update refs/heads/main\n\n    $ git log --oneline # CMD_10\n    b5f15a4 (HEAD) 5\n    50c2673 4\n    2c1ed1a 3\n    83f595c 2\n    edff563 1\n\n    $ git status # CMD_11\n    interactive rebase in progress; onto a36b6d5\n    Last commands done (3 commands done):\n       pick fd8f39c # 2026-09-25 Nikita Bobko/Nikita Bobko 4\n       pick e641e3f # 2026-09-25 Nikita Bobko/Nikita Bobko (HEAD -> main) 5\n      (see more in file .git/rebase-merge/done)\n    No commands remaining.\n    You are currently editing a commit while rebasing branch 'main' on 'a36b6d5'.\n      (use \"git commit --amend\" to amend the current commit)\n      (use \"git rebase --continue\" once you are satisfied with your changes)\n\n    nothing to commit, working tree clean\n\n    $ git branch --force main # CMD_12\n    fatal: cannot force update the branch 'main' used by worktree at '/Users/bobko/git-history-bug'\n\n    $ pwd # CMD_13: Yep, we are broken\n    /Users/bobko/git-history-bug\n\n## What goes wrong\n\nCMD_4 starts the rebase; CMD_7 runs git-history in the middle of it.\n\nCMD_9 and CMD_12 demonstrate the broken state (`git rebase --continue`\ncannot finish anymore).\n\n## Solutions that I thought of\n\n1. The obvious one is to just forbid git-history during\n   rebase/cherry-pick. Probably fine for an experimental command, but\n   I believe it would forbid valid workflows.\n\n2. Require using the explicit `--update-refs=head` flag when we are in\n   git rebase state. (Forbids valid workflows when combined with\n   `git rebase --update-refs`.)\n\n3. Implicitly use `--update-refs=head` flag when we are in git rebase\n   state. (Not something that users might expect. Certainly must be\n   documented in the git-history(1) man page.)\n\n4. Update all branches but the one currently being rebased. Sounds\n   complicated, but I haven't managed to think of a counter-example.\n\n   I was thinking that graphs like this might be problematic:\n\n      * 9cc305f (main) 5\n      | * 5d8f3d2 (b-4.5) 4.5\n      |/\n      * fbb1ec7 4\n      * b47bb7e (HEAD) 3 # stop interactive rebase here, and play with git-history\n      | * b052adc (b-2.5) 2.5\n      |/\n      * 106a0da 2\n      * edff563 1\n\n   But it looks like the end result is surprisingly \"self-consistent\"\n   even for such graphs. The user is certainly doing something weird,\n   but, what's important, the end result doesn't lead to the broken\n   state described in this bug report.\n\n   My intuition tells me something is off with the suggested\n   solution, though.\n\n5. Something else?\n\n## Environment\n\ngit version 2.55.0 (Homebrew), cpu: arm64\nDarwin 27.0.0 arm64 (macOS)\n\n## Related notes\n\n1. git-cherry-pick doesn't do a final ref update pass the way\n   git-rebase does, so it's not affected by this specific bug (please\n   correct me if I'm wrong), but it is affected by another kind of\n   interaction (see point 3 below).\n\n2. Even `git branch --force` refuses to change the ref that is\n   currently being rebased (see CMD_12). git-history must not be\n   allowed to do that either.\n\n3. What if we run git-history on one of the commits mentioned in the\n   git-rebase-todo file (descendants of the original HEAD) while we\n   are in rebase/cherry-pick state?\n\n   Should git-history update the git-rebase-todo file as well in such\n   a case or not? git-history tries too hard to update the branches, so\n   updating git-rebase-todo fits this model, but it definitely feels\n   \"invasive\".\n\n   (Currently, it doesn't. And it leads to the same sort of bug as in\n   the current bug report anyway: CMD_9)\n\n   (Some people might claim that this specific bug also applies to\n   git-cherry-pick but has a different symptom: the result of\n   git-history is silently ignored by git-cherry-pick)\n\n4. What about feature interaction with `git rebase --update-refs`?\n   (I have just learnt about `git rebase --update-refs` while writing\n   this bug report so I didn't think this interaction through)\n\n--\nNikita Bobko\n\n"}]}