Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safe git rebase

Tags:

git

rebase

Quite often, when working on one thing, I find some ugliness in unrelated code, fix it and commit separately. Usually, there are multiple such commits, as I find similar problems later.

Finally, I rebase (reorder and squash) so that the commits make more sense. Sometimes, I get merge conflicts and sometimes the resulting working tree differs from the one before rebasing.

  • Can such a difference occur even when there were no conflicts?
  • Is there a way to get a (huge blinking) warning when the difference occurs?
like image 794
maaartinus Avatar asked Oct 19 '22 03:10

maaartinus


1 Answers

Can such a difference occur even when there were no conflicts?

Maybe not, but human error is a factor we should always consider.

Is there a way to get a (huge blinking) warning when the difference occurs?

This should do:

git diff ORIG_HEAD HEAD

To do it automatically, use the post-rewrite hook (see Git Hooks):

post-rewrite

This hook is invoked by commands that rewrite commits (git commit --amend, git-rebase; currently git-filter-branch does not call it!). Its first argument denotes the command it was invoked by: currently one of amend or rebase. Further command-dependent arguments may be passed in the future.

Then in the hook script .git/hooks/post-rewrite we can compare ORIG_HEAD and HEAD, and emit a warning if different:

#!/bin/sh

diff_rebase() {
    # echo "Old HEAD: $(git rev-parse ORIG_HEAD)"
    # echo "New HEAD: $(git rev-parse HEAD)"
    if ! git diff --quiet ORIG_HEAD HEAD; then
        >&2 echo "NOTE: diff detected after rebase!"
    else
        echo "rebase well done"
    fi
}

# bypass git amend
[ "$1" = "rebase" ] && diff_rebase

To make the hook available globally, consider config core.hooksPath, e.g.:

git config --global core.hooksPath /usr/local/git-hooks/

Then save the script as /usr/local/git-hooks/post-rewrite, with executable permission set.

NOTE: unfortunately it seems there's a bug that interactive rebase, namely git rebase -i, doesn't trigger the hook, when a custom hooks dir is used. (I'm using git 2.9.2)

like image 93
ryenus Avatar answered Oct 24 '22 10:10

ryenus