414d924beb
A common scenario is if a user is working on a topic branch and they wish to make some changes to intermediate commits or autosquash, they would run something such as git rebase -i --onto master... master in order to preserve the merge base. This is useful when contributing a patch series to the Git mailing list, one often starts on top of the current 'master'. While developing the patches, 'master' is also developed further and it is sometimes not the best idea to keep rebasing on top of 'master', but to keep the base commit as-is. In addition to this, a user wishing to test individual commits in a topic branch without changing anything may run git rebase -x ./test.sh master... master Since rebasing onto the merge base of the branch and the upstream is such a common case, introduce the --keep-base option as a shortcut. This allows us to rewrite the above as git rebase -i --keep-base master and git rebase -x ./test.sh --keep-base master respectively. Add tests to ensure --keep-base works correctly in the normal case and fails when there are multiple merge bases, both in regular and interactive mode. Also, test to make sure conflicting options cause rebase to fail. While we're adding test cases, add a missing set_fake_editor call to 'rebase -i --onto master...side'. While we're documenting the --keep-base option, change an instance of "merge-base" to "merge base", which is the consistent spelling. Helped-by: Eric Sunshine <sunshine@sunshineco.com> Helped-by: Junio C Hamano <gitster@pobox.com> Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Helped-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Signed-off-by: Denton Liu <liu.denton@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
163 lines
3.6 KiB
Bash
Executable File
163 lines
3.6 KiB
Bash
Executable File
#!/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_expect_success 'rebase -i --onto master...topic' '
|
|
git reset --hard &&
|
|
git checkout topic &&
|
|
git reset --hard G &&
|
|
set_fake_editor &&
|
|
EXPECT_COUNT=1 git rebase -i --onto master...topic F &&
|
|
git rev-parse HEAD^1 >actual &&
|
|
git rev-parse C^0 >expect &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'rebase -i --onto master...' '
|
|
git reset --hard &&
|
|
git checkout topic &&
|
|
git reset --hard G &&
|
|
set_fake_editor &&
|
|
EXPECT_COUNT=1 git rebase -i --onto master... F &&
|
|
git rev-parse HEAD^1 >actual &&
|
|
git rev-parse C^0 >expect &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'rebase -i --onto master...side' '
|
|
git reset --hard &&
|
|
git checkout side &&
|
|
git reset --hard K &&
|
|
|
|
set_fake_editor &&
|
|
test_must_fail git rebase -i --onto master...side J
|
|
'
|
|
|
|
test_expect_success 'rebase --keep-base --onto incompatible' '
|
|
test_must_fail git rebase --keep-base --onto master...
|
|
'
|
|
|
|
test_expect_success 'rebase --keep-base --root incompatible' '
|
|
test_must_fail git rebase --keep-base --root
|
|
'
|
|
|
|
test_expect_success 'rebase --keep-base master from topic' '
|
|
git reset --hard &&
|
|
git checkout topic &&
|
|
git reset --hard G &&
|
|
|
|
git rebase --keep-base master &&
|
|
git rev-parse C >base.expect &&
|
|
git merge-base master HEAD >base.actual &&
|
|
test_cmp base.expect base.actual &&
|
|
|
|
git rev-parse HEAD~2 >actual &&
|
|
git rev-parse C^0 >expect &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'rebase --keep-base master from side' '
|
|
git reset --hard &&
|
|
git checkout side &&
|
|
git reset --hard K &&
|
|
|
|
test_must_fail git rebase --keep-base master
|
|
'
|
|
|
|
test_expect_success 'rebase -i --keep-base master from topic' '
|
|
git reset --hard &&
|
|
git checkout topic &&
|
|
git reset --hard G &&
|
|
|
|
set_fake_editor &&
|
|
EXPECT_COUNT=2 git rebase -i --keep-base master &&
|
|
git rev-parse C >base.expect &&
|
|
git merge-base master HEAD >base.actual &&
|
|
test_cmp base.expect base.actual &&
|
|
|
|
git rev-parse HEAD~2 >actual &&
|
|
git rev-parse C^0 >expect &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'rebase -i --keep-base master from side' '
|
|
git reset --hard &&
|
|
git checkout side &&
|
|
git reset --hard K &&
|
|
|
|
set_fake_editor &&
|
|
test_must_fail git rebase -i --keep-base master
|
|
'
|
|
|
|
test_done
|