Prefer rebase. Nice.
authorStephen Haberman <stephen@exigencecorp.com>
Fri, 20 Jun 2008 18:29:39 +0000 (13:29 -0500)
committerStephen Haberman <stephen@exigencecorp.com>
Fri, 20 Jun 2008 18:29:39 +0000 (13:29 -0500)
server/pre-receive-prefer-rebase [new file with mode: 0644]
tests/t2200-server-post-receive-email.sh
tests/t2300-server-pre-receive-prefer-rebase.sh [new file with mode: 0644]

diff --git a/server/pre-receive-prefer-rebase b/server/pre-receive-prefer-rebase
new file mode 100644 (file)
index 0000000..ba9e919
--- /dev/null
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+while read oldrev newrev refname ; do
+       if expr "$oldrev" : '0*$' >/dev/null ; then
+               exit 0
+       fi
+
+       # If the new ref is a merge, it'll have spaces in the parents log (ugly, yes)
+       git log -n 1 --pretty=format:%p $newrev | grep " "
+       if [ $? -ne 0 ] ; then
+               exit 0
+       fi
+
+       # If they are introducing non-merge commits /and/ merge commits, it could
+       # look like:
+       #
+       # * --- * --- * --- O
+       #        \           \
+       #         N --- N --- M
+       #
+       # They should have done a rebase.
+       #
+       # But if it looks like:
+       #
+       # * --- * --- * --- O
+       #        \           \
+       #         S --- N --- M
+       #
+       # Then they were correct in doing a merge as S was already shared.
+
+       baserev=$(git merge-base $oldrev $newrev)
+       base_to_old=$(git rev-list $baserev..$oldrev | wc -l)
+       base_to_new=$(git rev-list $baserev..$newrev | wc -l)
+       # includes the base_to_new includes both legs, so subtract to get new leg count
+       new_leg=$(expr $base_to_new - $base_to_old)
+       all_new=$(git rev-parse --not --branches | grep -v $(git rev-parse $refname) | git rev-list --stdin $oldrev..$newrev | wc -l)
+
+       # echo "new_leg=$new_leg"
+       # echo "all_new=$all_new"
+       if [ $all_new -eq $new_leg ] ; then
+               echo "----------------------------------------------------"
+               echo
+               echo "It looks like you should rebase"
+               echo
+               echo "----------------------------------------------------"
+               exit 1
+       fi
+done
+
index 42f8b82..006bd84 100644 (file)
@@ -4,8 +4,6 @@ test_description='server post-receive email notification'
 
 . ./test-lib.sh
 
-export POST_RECEIVE_EMAIL_DUMP=true
-
 test_expect_success 'setup' '
        echo "setup" >a &&
        git add a &&
diff --git a/tests/t2300-server-pre-receive-prefer-rebase.sh b/tests/t2300-server-pre-receive-prefer-rebase.sh
new file mode 100644 (file)
index 0000000..8fd15b4
--- /dev/null
@@ -0,0 +1,82 @@
+#!/bin/sh
+
+test_description='server pre-receive prefer rebase'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+       echo "setup" >a &&
+       git add a &&
+       git commit -m "setup" &&
+       git clone ./. server &&
+       rm -fr server/.git/hooks &&
+       git remote add origin ./server &&
+       git config --add branch.master.remote origin &&
+       git config --add branch.master.merge refs/heads/master &&
+       git fetch
+'
+
+install_server_hook 'pre-receive-prefer-rebase' 'pre-receive'
+
+test_expect_success 'all local changes do not need a merge' '
+       # server is on "setup"
+
+       # make an outstanding change for us--but do not push
+       echo "$test_name" >a.client1 &&
+       git add a.client1 &&
+       git commit -m "$test_name on client1" &&
+
+       # have another client commit (in this case, it is the server, but close enough)
+       cd server &&
+       echo "$test_name" >a.client2 &&
+       git add a.client2 &&
+       git commit -m "$test_name on client2" &&
+
+       # go back to our client and it will merge in our changes
+       cd .. &&
+       git pull &&
+
+       ! git push 2>push.err &&
+       cat push.err | grep "It looks like you should rebase" &&
+       git reset --hard origin/master
+'
+
+test_expect_success 'already shared topic changes do warrant a merge' '
+       # server is on "setup"
+
+       # make a change on topic for us and share it
+       git checkout -b topic master &&
+       echo "$test_name" >a.client1 &&
+       git add a.client1 &&
+       git commit -m "$test_name on client1 and topic" &&
+       git push origin topic &&
+
+       # make an outstanding change that we will have to merge later
+       echo "$test_name again" >>a.client1 &&
+       git commit -a -m "$test_name on client1 and topic again" &&
+
+       # have another client commit to master (in this case, it is the server, but close enough)
+       cd server &&
+       echo "$test_name" >a.client2 &&
+       git add a.client2 &&
+       git commit -m "$test_name on client2" &&
+
+       # go back to our client and it will merge in our changes
+       cd .. &&
+       git checkout master &&
+       git pull &&
+       git merge topic &&
+
+       git push
+'
+
+test_expect_success 'simple commit' '
+       # go back to topic and make a simple commit/push as a sanity check
+       git checkout topic &&
+       echo "$test_name" >>a.client1 &&
+       git commit -a -m "$test_name on client1 and topic" &&
+       git push
+'
+
+test_done
+