aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNanako Shiraishi <nanako3@lavabit.com>2010-01-07 20:05:02 +0900
committerJunio C Hamano <gitster@pobox.com>2010-01-07 11:14:39 -0800
commit9f21e97ddccf114a6919cf4b8cf57c2838328f36 (patch)
tree6096cbd783e73d10ca772012fef8289bce72f22c
parent61dfa1bb6710690e53fa20bc3ddd1f5fbe8c1d22 (diff)
downloadgit-9f21e97ddccf114a6919cf4b8cf57c2838328f36.tar.gz
git-9f21e97ddccf114a6919cf4b8cf57c2838328f36.tar.xz
rebase: fix --onto A...B parsing and add tests
The previous patch didn't parse "rebase --onto A...B" correctly when A isn't an empty string. It also tried to be careful to notice a case in which there are more than one merge bases, but forgot to give --all option to merge-base, making the test pointless. Fix these problems and add a test script to verify. Improvements to the script to parse A...B syntax was taken from review comments by Johannes Schindelin. Signed-off-by: しらいし ななこ <nanako3@lavabit.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rwxr-xr-xgit-rebase.sh33
-rwxr-xr-xt/t3415-rebase-onto-threedots.sh75
2 files changed, 94 insertions, 14 deletions
diff --git a/git-rebase.sh b/git-rebase.sh
index 6503113a8..9bd89746a 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -419,22 +419,27 @@ fi
# Make sure the branch to rebase onto is valid.
onto_name=${newbase-"$upstream_name"}
-if left=$(expr "$onto_name" : '\(.*\)\.\.\.') &&
- right=$(expr "$onto_name" : '\.\.\.\(.*\)$') &&
- : ${left:=HEAD} ${right:=HEAD} &&
- onto=$(git merge-base "$left" "$right")
-then
- case "$onto" in
- ?*"$LF"?*)
- die "$onto_name: there are more than one merge bases"
- ;;
- '')
+case "$onto_name" in
+*...*)
+ if left=${onto_name%...*} right=${onto_name#*...} &&
+ onto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})
+ then
+ case "$onto" in
+ ?*"$LF"?*)
+ die "$onto_name: there are more than one merge bases"
+ ;;
+ '')
+ die "$onto_name: there is no merge base"
+ ;;
+ esac
+ else
die "$onto_name: there is no merge base"
- ;;
- esac
-else
+ fi
+ ;;
+*)
onto=$(git rev-parse --verify "${onto_name}^0") || exit
-fi
+ ;;
+esac
# If a hook exists, give it a chance to interrupt
run_pre_rebase_hook "$upstream_arg" "$@"
diff --git a/t/t3415-rebase-onto-threedots.sh b/t/t3415-rebase-onto-threedots.sh
new file mode 100755
index 000000000..b09e907c3
--- /dev/null
+++ b/t/t3415-rebase-onto-threedots.sh
@@ -0,0 +1,75 @@
+#!/bin/sh
+
+test_description='git rebase --onto A...B'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-rebase.sh"
+
+# Rebase only the tip commit of "topic" on merge base between "master"
+# and "topic". Cannot do this for "side" with "master" because there
+# is no single merge base.
+#
+#
+# F---G topic G'
+# / /
+# A---B---C---D---E master --> A---B---C---D---E
+# \ \ /
+# \ x
+# \ / \
+# H---I---J---K side
+
+test_expect_success setup '
+ test_commit A &&
+ test_commit B &&
+ git branch side &&
+ test_commit C &&
+ git branch topic &&
+ git checkout side &&
+ test_commit H &&
+ git checkout master &&
+ test_tick &&
+ git merge H &&
+ git tag D &&
+ test_commit E &&
+ git checkout topic &&
+ test_commit F &&
+ test_commit G &&
+ git checkout side &&
+ test_tick &&
+ git merge C &&
+ git tag I &&
+ test_commit J &&
+ test_commit K
+'
+
+test_expect_success 'rebase --onto master...topic' '
+ git reset --hard &&
+ git checkout topic &&
+ git reset --hard G &&
+
+ git rebase --onto master...topic F &&
+ git rev-parse HEAD^1 >actual &&
+ git rev-parse C^0 >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'rebase --onto master...' '
+ git reset --hard &&
+ git checkout topic &&
+ git reset --hard G &&
+
+ git rebase --onto master... F &&
+ git rev-parse HEAD^1 >actual &&
+ git rev-parse C^0 >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'rebase --onto master...side' '
+ git reset --hard &&
+ git checkout side &&
+ git reset --hard K &&
+
+ test_must_fail git rebase --onto master...side J
+'
+
+test_done