From: Stephen Haberman Date: Fri, 20 Jun 2008 18:29:39 +0000 (-0500) Subject: Prefer rebase. Nice. X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=c4fd0964f1e58fb648ad49648a60716703133c53;p=git-central.git Prefer rebase. Nice. --- diff --git a/server/pre-receive-prefer-rebase b/server/pre-receive-prefer-rebase new file mode 100644 index 0000000..ba9e919 --- /dev/null +++ b/server/pre-receive-prefer-rebase @@ -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 + diff --git a/tests/t2200-server-post-receive-email.sh b/tests/t2200-server-post-receive-email.sh index 42f8b82..006bd84 100644 --- a/tests/t2200-server-post-receive-email.sh +++ b/tests/t2200-server-post-receive-email.sh @@ -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 index 0000000..8fd15b4 --- /dev/null +++ b/tests/t2300-server-pre-receive-prefer-rebase.sh @@ -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 +