git/t/t3421-rebase-topology-linear.sh
Ben Woosley 79f43447d2 git-rebase--merge: don't include absent parent as a base
Absent this fix, attempts to rebase an orphan branch using "rebase -m"
fails with:

    $ git rebase -m ORPHAN_TARGET_BASE
    First, rewinding head to replay your work on top of it...
    fatal: Could not parse object 'ORPHAN_ROOT_SHA^'
    Unknown exit code (128) from command: git-merge-recursive ORPHAN_ROOT_SHA^ -- HEAD ORPHAN_ROOT_SHA

To fix, this will only include the rebase root's parent as a base if it exists,
so that in cases of rebasing an orphan branch, it is a simple two-way merge.

Note the default rebase behavior does not fail:

    $ git rebase ORPHAN_TARGET_BASE
    First, rewinding head to replay your work on top of it...
    Applying: ORPHAN_ROOT_COMMIT_MSG
    Using index info to reconstruct a base tree...

A few tests were expecting the old behaviour to forbid rebasing such
a history with "rebase -m", which now need to expect them to succeed.

Signed-off-by: Ben Woosley <ben.woosley@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-24 12:05:08 -07:00

351 lines
7.3 KiB
Bash
Executable File

#!/bin/sh
test_description='basic rebase topology tests'
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
# a---b---c
# \
# d---e
test_expect_success 'setup' '
test_commit a &&
test_commit b &&
test_commit c &&
git checkout b &&
test_commit d &&
test_commit e
'
test_run_rebase () {
result=$1
shift
test_expect_$result "simple rebase $*" "
reset_rebase &&
git rebase $* c e &&
test_cmp_rev c HEAD~2 &&
test_linear_range 'd e' c..
"
}
test_run_rebase success ''
test_run_rebase success -m
test_run_rebase success -i
test_run_rebase success -p
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* is no-op if upstream is an ancestor" "
reset_rebase &&
git rebase $* b e &&
test_cmp_rev e HEAD
"
}
test_run_rebase success ''
test_run_rebase success -m
test_run_rebase success -i
test_run_rebase success -p
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* -f rewrites even if upstream is an ancestor" "
reset_rebase &&
git rebase $* -f b e &&
! test_cmp_rev e HEAD &&
test_cmp_rev b HEAD~2 &&
test_linear_range 'd e' b..
"
}
test_run_rebase success ''
test_run_rebase success -m
test_run_rebase success -i
test_run_rebase failure -p
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* fast-forwards from ancestor of upstream" "
reset_rebase &&
git rebase $* e b &&
test_cmp_rev e HEAD
"
}
test_run_rebase success ''
test_run_rebase success -m
test_run_rebase success -i
test_run_rebase success -p
# f
# /
# a---b---c---g---h
# \
# d---gp--i
#
# gp = cherry-picked g
# h = reverted g
#
# Reverted patches are there for tests to be able to check if a commit
# that introduced the same change as another commit is
# dropped. Without reverted commits, we could get false positives
# because applying the patch succeeds, but simply results in no
# changes.
test_expect_success 'setup of linear history for range selection tests' '
git checkout c &&
test_commit g &&
revert h g &&
git checkout d &&
cherry_pick gp g &&
test_commit i &&
git checkout b &&
test_commit f
'
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* drops patches in upstream" "
reset_rebase &&
git rebase $* h i &&
test_cmp_rev h HEAD~2 &&
test_linear_range 'd i' h..
"
}
test_run_rebase success ''
test_run_rebase failure -m
test_run_rebase success -i
test_run_rebase success -p
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* can drop last patch if in upstream" "
reset_rebase &&
git rebase $* h gp &&
test_cmp_rev h HEAD^ &&
test_linear_range 'd' h..
"
}
test_run_rebase success ''
test_run_rebase failure -m
test_run_rebase success -i
test_run_rebase success -p
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* --onto drops patches in upstream" "
reset_rebase &&
git rebase $* --onto f h i &&
test_cmp_rev f HEAD~2 &&
test_linear_range 'd i' f..
"
}
test_run_rebase success ''
test_run_rebase failure -m
test_run_rebase success -i
test_run_rebase success -p
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* --onto does not drop patches in onto" "
reset_rebase &&
git rebase $* --onto h f i &&
test_cmp_rev h HEAD~3 &&
test_linear_range 'd gp i' h..
"
}
test_run_rebase success ''
test_run_rebase success -m
test_run_rebase success -i
test_run_rebase success -p
# a---b---c---j!
# \
# d---k!--l
#
# ! = empty
test_expect_success 'setup of linear history for empty commit tests' '
git checkout c &&
make_empty j &&
git checkout d &&
make_empty k &&
test_commit l
'
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* drops empty commit" "
reset_rebase &&
git rebase $* c l &&
test_cmp_rev c HEAD~2 &&
test_linear_range 'd l' c..
"
}
test_run_rebase success ''
test_run_rebase success -m
test_run_rebase success -i
test_run_rebase success -p
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* --keep-empty" "
reset_rebase &&
git rebase $* --keep-empty c l &&
test_cmp_rev c HEAD~3 &&
test_linear_range 'd k l' c..
"
}
test_run_rebase success ''
test_run_rebase failure -m
test_run_rebase success -i
test_run_rebase failure -p
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* --keep-empty keeps empty even if already in upstream" "
reset_rebase &&
git rebase $* --keep-empty j l &&
test_cmp_rev j HEAD~3 &&
test_linear_range 'd k l' j..
"
}
test_run_rebase success ''
test_run_rebase failure -m
test_run_rebase failure -i
test_run_rebase failure -p
# m
# /
# a---b---c---g
#
# x---y---bp
#
# bp = cherry-picked b
# m = reverted b
#
# Reverted patches are there for tests to be able to check if a commit
# that introduced the same change as another commit is
# dropped. Without reverted commits, we could get false positives
# because applying the patch succeeds, but simply results in no
# changes.
test_expect_success 'setup of linear history for test involving root' '
git checkout b &&
revert m b &&
git checkout --orphan disjoint &&
git rm -rf . &&
test_commit x &&
test_commit y &&
cherry_pick bp b
'
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* --onto --root" "
reset_rebase &&
git rebase $* --onto c --root y &&
test_cmp_rev c HEAD~2 &&
test_linear_range 'x y' c..
"
}
test_run_rebase success ''
test_run_rebase success -m
test_run_rebase success -i
test_run_rebase success -p
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* without --onto --root with disjoint history" "
reset_rebase &&
git rebase $* c y &&
test_cmp_rev c HEAD~2 &&
test_linear_range 'x y' c..
"
}
test_run_rebase success ''
test_run_rebase success -m
test_run_rebase success -i
test_run_rebase failure -p
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* --onto --root drops patch in onto" "
reset_rebase &&
git rebase $* --onto m --root bp &&
test_cmp_rev m HEAD~2 &&
test_linear_range 'x y' m..
"
}
test_run_rebase success ''
test_run_rebase failure -m
test_run_rebase success -i
test_run_rebase success -p
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* --onto --root with merge-base does not go to root" "
reset_rebase &&
git rebase $* --onto m --root g &&
test_cmp_rev m HEAD~2 &&
test_linear_range 'c g' m..
"
}
test_run_rebase success ''
test_run_rebase success -m
test_run_rebase success -i
test_run_rebase failure -p
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* without --onto --root with disjoint history drops patch in onto" "
reset_rebase &&
git rebase $* m bp &&
test_cmp_rev m HEAD~2 &&
test_linear_range 'x y' m..
"
}
test_run_rebase success ''
test_run_rebase failure -m
test_run_rebase success -i
test_run_rebase failure -p
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* --root on linear history is a no-op" "
reset_rebase &&
git rebase $* --root c &&
test_cmp_rev c HEAD
"
}
test_run_rebase failure ''
test_run_rebase failure -m
test_run_rebase failure -i
test_run_rebase failure -p
test_run_rebase () {
result=$1
shift
test_expect_$result "rebase $* -f --root on linear history causes re-write" "
reset_rebase &&
git rebase $* -f --root c &&
! test_cmp_rev a HEAD~2 &&
test_linear_range 'a b c' HEAD
"
}
test_run_rebase success ''
test_run_rebase success -m
test_run_rebase success -i
test_run_rebase success -p
test_done