Search code examples
gitmacos

Git corrupted? `reword` of `git rebase -i` suddenly stopped working


TL;DR

I had been using reword instruction of git rebase -i with no problem for a few years.

However, it no longer works only in one of my local Git repositories.

Strangely, just forking the repository locally resolves the problem.

How to Reproduce

  1. Confirms no rebase is in progress and the working directory is clean.

    $ git status
    On branch x
    nothing to commit, working tree clean
    
    $ git rebase --abort
    fatal: no rebase in progress
    
  2. Starts an interactive rebase.

    $ git rebase -i develop
    
  3. Edits the changelist.

    pick 0a280af1 commit_1
    pick 4c37991e commit_2
    - pick 09191dca commit_3
    + reword 09191dca commit_3
    pick cb098966 commit_4
    pick 670ce5d9 commit_5
    
  4. Edits the commit message when prompted.

  5. reword itself succeeds but the pick right after that fails for unknown reason.

    • commit_4_{a|b}.txt in the error message are already tracked and commit_4 edits them.

    • The other commits (i.e. commit_{1|2|3|5}) don't touch them.

    • As confirmed in the step 1 above, the working directory was clean (no local change) at the time of starting git rebase -i.

    [detached HEAD 79925137] new_commit_3
     Date: Mon Sep 2 15:55:29 2024 +0900
     2 files changed, 185 insertions(+)
     create mode 100644 commit_3_a.txt
     create mode 100644 commit_3_b.txt
    error: Your local changes to the following files would be overwritten by merge:
        commit_4_a.txt
        commit_4_b.txt
    Please commit your changes or stash them before you merge.
    Aborting
    hint: Could not execute the todo command
    hint:
    hint:     pick cb0989660941c763e6935d63105205e296a2c11f commit_4
    hint:
    hint: It has been rescheduled; To edit the command before continuing, please
    hint: edit the todo list first:
    hint:
    hint:     git rebase --edit-todo
    hint:     git rebase --continue
    

Workaround

I have a strange workaround.

  1. Locally forks the repository.

    $ cd /path/to/new_directory
    $ git clone /path/to/original_project
    
  2. Executes exactly the same steps shown in How to Reproduce section above.

  3. It works like a charm.

Environment

  • macOS Sonoma (M3 Apple Silicon)

  • Git 2.46.0 (installed via Homebrew)

Question

How can I debug the problem?


Solution

  • TL;DR

    The cache of a Git submodule (i.e. .git/modules) was corrupted. Just removing the directory and re-initializing the submodule resolved the problem.

    I don't know why, though.


    As written in this comment, I compared the output of GIT_TRACE=1 git rebase -i develop executed in the original problematic project and the one executed in a non problematic local fork to find that I initialized a Git submodule only in the former case.

    So I tried these steps:

    1. I executed git submodule deinit <directory name> to de-initialize the submodule in the former repository. After that, reword started to work with no problem.

    2. That said, I do need the submodule. So I again executed git submodule init. This made reword fail again.

    3. Then, in the non problematic fork, I executed git submodule init. Still reword was working.

    This debugging implies the cache of the submodule (i.e. .git/modules) in the former repository was corrupted (though git gc and git fsck didn't work).

    It should not matter because the series of the commits being rebased are completely irrelevant to and independent of the submodule's contents. But anyway I tried:

    1. git submodule deinit <directory name>

    2. mv .git/modules/ .git/modules.bak (removes the submodule cache)

    3. git submodule init

    4. git submodule update

    Now reword is working again.