Search code examples
gitrebase

How do you get a lost "autostash" commit from `git rebase --autostash`


When using git rebase --autostash, git automatically creates an "autostash" commit, and will re-apply it after a successful rebase.

But in case the rebasing is aborted (e.g. by using :cq in Vim when it's an interactive rebase), the autostash-commit might end up as a dangling commit.

Git 2.9.0


Solution

  • Git 2.10 (Q3 2016) should avoid that issue entirely.

    See commit 33ba9c6 (29 Jun 2016) by Patrick Steinhardt (pks-t).
    (Merged by Junio C Hamano -- gitster -- in commit 5eb1e9f, 13 Jul 2016)

    rebase -i: restore autostash on abort

    When we abort an interactive rebase we do so by calling die_abort, which cleans up after us by removing the rebase state directory.
    If the user has requested to use the autostash feature, though, the state directory may also contain a reference to the autostash, which will now be deleted.

    Fix the issue by trying to re-apply the autostash in die_abort.
    This will also handle the case where the autostash does not apply cleanly anymore by recording it in a user-visible stash.


    Note that the same kid of issue cropped back in Git 2.39:

    With Git 2.47 (Q4 2024), batch 19, "git rebase --autostash"(man) failed to resurrect the autostashed changes when the command gets aborted after giving back control asking for help in conflict resolution.

    See commit bf6ab08 (02 Sep 2024) by Phillip Wood (phillipwood).
    (Merged by Junio C Hamano -- gitster -- in commit 2b800ec, 20 Sep 2024)

    rebase: apply and cleanup autostash when rebase fails to start

    Reported-by: Brian Lyles
    Signed-off-by: Phillip Wood

    If "git rebase"(man) fails to start after stashing the users uncommitted changes then it forgets to restore the stashed changes and remove the state directory.
    To make matters worse, running "git rebase --abort"(man) to apply the stashed changes and cleanup the state directory fails because the state directory only contains the autostash file and is missing the head-name and onto files required by read_basic_state().

    Fix this by applying the autostash and removing the state directory if the pre-rebase hook or initial checkout fail.
    This matches what finish_rebase() does at the end of a successful rebase.
    If the user modifies any files after the autostash is created it is possible there will be conflicts when the autostash is applied.
    In that case apply_autostash() saves the stash in a new entry under refs/stash and so it is safe to remove the state directory containing the autostash file.

    New tests are added to check the autostash is applied and the state directory is removed if the rebase fails to start.
    Checks are also added to some existing tests in order to ensure there is no state directory left behind when a rebase fails to start and no autostash has been created.