Undoing a git rebase

前端 未结 18 1412
孤城傲影
孤城傲影 2020-11-22 02:41

Does anybody know how to easily undo a git rebase?

The only way that comes to mind is to go at it manually:

  • git checkout the commit parent to both of t
18条回答
  •  迷失自我
    2020-11-22 03:05

    It annoys me to no end that none of these answers is fully automatic, despite the fact that it should be automatable (at least mostly). I created a set of aliases to try to remedy this:

    # Useful commands
    #################
    
    # Undo the last rebase
    undo-rebase = "! f() { : git reset ; PREV_COMMIT=`git x-rev-before-rebase` && git reset --merge \"$PREV_COMMIT\" \"$@\";}; f"
    
    # See what changed since the last rebase
    rdiff = "!f() { : git diff ; git diff `git x-rev-before-rebase` "$@";}; f"
    
    # Helpers
    ########
    # Get the revision before the last rebase started
    x-rev-before-rebase = !git reflog --skip=1 -1 \"`git x-start-of-rebase`\" --format=\"%gD\"
    
    # Get the revision that started the rebase
    x-start-of-rebase = reflog --grep-reflog '^rebase (start)' -1 --format="%gD"
    

    You should be able to tweak this to allow going back an arbitrary number of rebases pretty easily (juggling the args is the trickiest part), which can be useful if you do a number of rebases in quick succession and mess something up along the way.

    Caveats

    It will get confused if any commit messages begin with "rebase (start)" (please don't do this). You could make the regex more resilient to improve the situation by matching something like this for your regex:

     --grep-reflog "^rebase (start): checkout " 
    

    WARNING: not tested (regex may need adjustments)

    The reason I haven't done this is because I'm not 100% that a rebase always begins with a checkout. Can anyone confirm this?

    [If you're curious about the null (:) commands at the beginning of the function, that's a way of setting up bash completions for the aliases]

提交回复
热议问题