Merge branch 'js/rebase-r-strategy'
"git rebase --rebase-merges" learned to drive different merge strategies and pass strategy specific options to them. * js/rebase-r-strategy: t3427: accelerate this test by using fast-export and fast-import rebase -r: do not (re-)generate root commits with `--root` *and* `--onto` t3418: test `rebase -r` with merge strategies t/lib-rebase: prepare for testing `git rebase --rebase-merges` rebase -r: support merge strategies other than `recursive` t3427: fix another incorrect assumption t3427: accommodate for the `rebase --merge` backend having been replaced t3427: fix erroneous assumption t3427: condense the unnecessarily repetitive test cases into three t3427: move the `filter-branch` invocation into the `setup` case t3427: simplify the `setup` test case significantly t3427: add a clarifying comment rebase: fold git-rebase--common into the -p backend sequencer: the `am` and `rebase--interactive` scripts are gone .gitignore: there is no longer a built-in `git-rebase--interactive` t3400: stop referring to the scripted rebase Drop unused git-rebase--am.sh
This commit is contained in:
@ -543,8 +543,6 @@ In addition, the following pairs of options are incompatible:
|
|||||||
* --preserve-merges and --interactive
|
* --preserve-merges and --interactive
|
||||||
* --preserve-merges and --signoff
|
* --preserve-merges and --signoff
|
||||||
* --preserve-merges and --rebase-merges
|
* --preserve-merges and --rebase-merges
|
||||||
* --rebase-merges and --strategy
|
|
||||||
* --rebase-merges and --strategy-option
|
|
||||||
|
|
||||||
BEHAVIORAL DIFFERENCES
|
BEHAVIORAL DIFFERENCES
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@ -62,7 +62,7 @@ struct rebase_options {
|
|||||||
const char *onto_name;
|
const char *onto_name;
|
||||||
const char *revisions;
|
const char *revisions;
|
||||||
const char *switch_to;
|
const char *switch_to;
|
||||||
int root;
|
int root, root_with_onto;
|
||||||
struct object_id *squash_onto;
|
struct object_id *squash_onto;
|
||||||
struct commit *restrict_revision;
|
struct commit *restrict_revision;
|
||||||
int dont_finish_rebase;
|
int dont_finish_rebase;
|
||||||
@ -374,6 +374,7 @@ static int run_rebase_interactive(struct rebase_options *opts,
|
|||||||
flags |= abbreviate_commands ? TODO_LIST_ABBREVIATE_CMDS : 0;
|
flags |= abbreviate_commands ? TODO_LIST_ABBREVIATE_CMDS : 0;
|
||||||
flags |= opts->rebase_merges ? TODO_LIST_REBASE_MERGES : 0;
|
flags |= opts->rebase_merges ? TODO_LIST_REBASE_MERGES : 0;
|
||||||
flags |= opts->rebase_cousins > 0 ? TODO_LIST_REBASE_COUSINS : 0;
|
flags |= opts->rebase_cousins > 0 ? TODO_LIST_REBASE_COUSINS : 0;
|
||||||
|
flags |= opts->root_with_onto ? TODO_LIST_ROOT_WITH_ONTO : 0;
|
||||||
flags |= command == ACTION_SHORTEN_OIDS ? TODO_LIST_SHORTEN_IDS : 0;
|
flags |= command == ACTION_SHORTEN_OIDS ? TODO_LIST_SHORTEN_IDS : 0;
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
@ -1833,15 +1834,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||||||
"'--reschedule-failed-exec'"));
|
"'--reschedule-failed-exec'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.rebase_merges) {
|
|
||||||
if (strategy_options.nr)
|
|
||||||
die(_("cannot combine '--rebase-merges' with "
|
|
||||||
"'--strategy-option'"));
|
|
||||||
if (options.strategy)
|
|
||||||
die(_("cannot combine '--rebase-merges' with "
|
|
||||||
"'--strategy'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options.root) {
|
if (!options.root) {
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
struct branch *branch;
|
struct branch *branch;
|
||||||
@ -1872,7 +1864,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||||||
options.squash_onto = &squash_onto;
|
options.squash_onto = &squash_onto;
|
||||||
options.onto_name = squash_onto_name =
|
options.onto_name = squash_onto_name =
|
||||||
xstrdup(oid_to_hex(&squash_onto));
|
xstrdup(oid_to_hex(&squash_onto));
|
||||||
}
|
} else
|
||||||
|
options.root_with_onto = 1;
|
||||||
|
|
||||||
options.upstream_name = NULL;
|
options.upstream_name = NULL;
|
||||||
options.upstream = NULL;
|
options.upstream = NULL;
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
|
18
sequencer.c
18
sequencer.c
@ -3364,6 +3364,9 @@ static int do_merge(struct repository *r,
|
|||||||
struct commit *head_commit, *merge_commit, *i;
|
struct commit *head_commit, *merge_commit, *i;
|
||||||
struct commit_list *bases, *j, *reversed = NULL;
|
struct commit_list *bases, *j, *reversed = NULL;
|
||||||
struct commit_list *to_merge = NULL, **tail = &to_merge;
|
struct commit_list *to_merge = NULL, **tail = &to_merge;
|
||||||
|
const char *strategy = !opts->xopts_nr &&
|
||||||
|
(!opts->strategy || !strcmp(opts->strategy, "recursive")) ?
|
||||||
|
NULL : opts->strategy;
|
||||||
struct merge_options o;
|
struct merge_options o;
|
||||||
int merge_arg_len, oneline_offset, can_fast_forward, ret, k;
|
int merge_arg_len, oneline_offset, can_fast_forward, ret, k;
|
||||||
static struct lock_file lock;
|
static struct lock_file lock;
|
||||||
@ -3516,7 +3519,7 @@ static int do_merge(struct repository *r,
|
|||||||
goto leave_merge;
|
goto leave_merge;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (to_merge->next) {
|
if (strategy || to_merge->next) {
|
||||||
/* Octopus merge */
|
/* Octopus merge */
|
||||||
struct child_process cmd = CHILD_PROCESS_INIT;
|
struct child_process cmd = CHILD_PROCESS_INIT;
|
||||||
|
|
||||||
@ -3530,7 +3533,14 @@ static int do_merge(struct repository *r,
|
|||||||
cmd.git_cmd = 1;
|
cmd.git_cmd = 1;
|
||||||
argv_array_push(&cmd.args, "merge");
|
argv_array_push(&cmd.args, "merge");
|
||||||
argv_array_push(&cmd.args, "-s");
|
argv_array_push(&cmd.args, "-s");
|
||||||
argv_array_push(&cmd.args, "octopus");
|
if (!strategy)
|
||||||
|
argv_array_push(&cmd.args, "octopus");
|
||||||
|
else {
|
||||||
|
argv_array_push(&cmd.args, strategy);
|
||||||
|
for (k = 0; k < opts->xopts_nr; k++)
|
||||||
|
argv_array_pushf(&cmd.args,
|
||||||
|
"-X%s", opts->xopts[k]);
|
||||||
|
}
|
||||||
argv_array_push(&cmd.args, "--no-edit");
|
argv_array_push(&cmd.args, "--no-edit");
|
||||||
argv_array_push(&cmd.args, "--no-ff");
|
argv_array_push(&cmd.args, "--no-ff");
|
||||||
argv_array_push(&cmd.args, "--no-log");
|
argv_array_push(&cmd.args, "--no-log");
|
||||||
@ -4554,6 +4564,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,
|
|||||||
{
|
{
|
||||||
int keep_empty = flags & TODO_LIST_KEEP_EMPTY;
|
int keep_empty = flags & TODO_LIST_KEEP_EMPTY;
|
||||||
int rebase_cousins = flags & TODO_LIST_REBASE_COUSINS;
|
int rebase_cousins = flags & TODO_LIST_REBASE_COUSINS;
|
||||||
|
int root_with_onto = flags & TODO_LIST_ROOT_WITH_ONTO;
|
||||||
struct strbuf buf = STRBUF_INIT, oneline = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT, oneline = STRBUF_INIT;
|
||||||
struct strbuf label = STRBUF_INIT;
|
struct strbuf label = STRBUF_INIT;
|
||||||
struct commit_list *commits = NULL, **tail = &commits, *iter;
|
struct commit_list *commits = NULL, **tail = &commits, *iter;
|
||||||
@ -4720,7 +4731,8 @@ static int make_script_with_merges(struct pretty_print_context *pp,
|
|||||||
|
|
||||||
if (!commit)
|
if (!commit)
|
||||||
strbuf_addf(out, "%s %s\n", cmd_reset,
|
strbuf_addf(out, "%s %s\n", cmd_reset,
|
||||||
rebase_cousins ? "onto" : "[new root]");
|
rebase_cousins || root_with_onto ?
|
||||||
|
"onto" : "[new root]");
|
||||||
else {
|
else {
|
||||||
const char *to = NULL;
|
const char *to = NULL;
|
||||||
|
|
||||||
|
@ -143,6 +143,12 @@ int sequencer_remove_state(struct replay_opts *opts);
|
|||||||
*/
|
*/
|
||||||
#define TODO_LIST_REBASE_COUSINS (1U << 4)
|
#define TODO_LIST_REBASE_COUSINS (1U << 4)
|
||||||
#define TODO_LIST_APPEND_TODO_HELP (1U << 5)
|
#define TODO_LIST_APPEND_TODO_HELP (1U << 5)
|
||||||
|
/*
|
||||||
|
* When generating a script that rebases merges with `--root` *and* with
|
||||||
|
* `--onto`, we do not want to re-generate the root commits.
|
||||||
|
*/
|
||||||
|
#define TODO_LIST_ROOT_WITH_ONTO (1U << 6)
|
||||||
|
|
||||||
|
|
||||||
int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,
|
int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,
|
||||||
const char **argv, unsigned flags);
|
const char **argv, unsigned flags);
|
||||||
|
@ -44,10 +44,10 @@ set_fake_editor () {
|
|||||||
rm -f "$1"
|
rm -f "$1"
|
||||||
echo 'rebase -i script before editing:'
|
echo 'rebase -i script before editing:'
|
||||||
cat "$1".tmp
|
cat "$1".tmp
|
||||||
action=pick
|
action=\&
|
||||||
for line in $FAKE_LINES; do
|
for line in $FAKE_LINES; do
|
||||||
case $line in
|
case $line in
|
||||||
pick|p|squash|s|fixup|f|edit|e|reword|r|drop|d)
|
pick|p|squash|s|fixup|f|edit|e|reword|r|drop|d|label|l|reset|r|merge|m)
|
||||||
action="$line";;
|
action="$line";;
|
||||||
exec_*|x_*|break|b)
|
exec_*|x_*|break|b)
|
||||||
echo "$line" | sed 's/_/ /g' >> "$1";;
|
echo "$line" | sed 's/_/ /g' >> "$1";;
|
||||||
@ -58,11 +58,12 @@ set_fake_editor () {
|
|||||||
bad)
|
bad)
|
||||||
action="badcmd";;
|
action="badcmd";;
|
||||||
fakesha)
|
fakesha)
|
||||||
|
test \& != "$action" || action=pick
|
||||||
echo "$action XXXXXXX False commit" >> "$1"
|
echo "$action XXXXXXX False commit" >> "$1"
|
||||||
action=pick;;
|
action=pick;;
|
||||||
*)
|
*)
|
||||||
sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1"
|
sed -n "${line}s/^[a-z][a-z]*/$action/p" < "$1".tmp >> "$1"
|
||||||
action=pick;;
|
action=\&;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
echo 'rebase -i script after editing:'
|
echo 'rebase -i script after editing:'
|
||||||
|
@ -120,6 +120,20 @@ test_expect_success REBASE_P 'rebase passes merge strategy options correctly' '
|
|||||||
git rebase --continue
|
git rebase --continue
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'rebase -r passes merge strategy options correctly' '
|
||||||
|
rm -fr .git/rebase-* &&
|
||||||
|
git reset --hard commit-new-file-F3-on-topic-branch &&
|
||||||
|
test_commit merge-theirs &&
|
||||||
|
git reset --hard HEAD^ &&
|
||||||
|
test_commit some-other-commit &&
|
||||||
|
test_tick &&
|
||||||
|
git merge --no-ff merge-theirs &&
|
||||||
|
FAKE_LINES="1 3 edit 4 5 7 8 9" git rebase -i -f -r -m \
|
||||||
|
-s recursive --strategy-option=theirs HEAD~2 &&
|
||||||
|
test_commit force-change-ours &&
|
||||||
|
git rebase --continue
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success '--skip after failed fixup cleans commit message' '
|
test_expect_success '--skip after failed fixup cleans commit message' '
|
||||||
test_when_finished "test_might_fail git rebase --abort" &&
|
test_when_finished "test_might_fail git rebase --abort" &&
|
||||||
git checkout -b with-conflicting-fixup &&
|
git checkout -b with-conflicting-fixup &&
|
||||||
|
@ -76,14 +76,4 @@ test_expect_success REBASE_P \
|
|||||||
test_must_fail git rebase --preserve-merges --rebase-merges A
|
test_must_fail git rebase --preserve-merges --rebase-merges A
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success '--rebase-merges incompatible with --strategy' '
|
|
||||||
git checkout B^0 &&
|
|
||||||
test_must_fail git rebase --rebase-merges -s resolve A
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success '--rebase-merges incompatible with --strategy-option' '
|
|
||||||
git checkout B^0 &&
|
|
||||||
test_must_fail git rebase --rebase-merges -Xignore-space-change A
|
|
||||||
'
|
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
@ -11,113 +11,99 @@ commit_message() {
|
|||||||
git log --pretty=format:%s -1 "$1"
|
git log --pretty=format:%s -1 "$1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# There are a few bugs in the rebase with regards to the subtree strategy, and
|
||||||
|
# this test script tries to document them. First, the following commit history
|
||||||
|
# is generated (the onelines are shown, time flows from left to right):
|
||||||
|
#
|
||||||
|
# master1 - master2 - master3
|
||||||
|
# \
|
||||||
|
# README ---------------------- Add subproject master - master4 - files_subtree/master5
|
||||||
|
#
|
||||||
|
# Where the merge moves the files master[123].t into the subdirectory
|
||||||
|
# files_subtree/ and master4 as well as files_subtree/master5 add files to that
|
||||||
|
# directory directly.
|
||||||
|
#
|
||||||
|
# Then, in subsequent test cases, `git filter-branch` is used to distill just
|
||||||
|
# the commits that touch files_subtree/. To give it a final pre-rebase touch,
|
||||||
|
# an empty commit is added on top. The pre-rebase commit history looks like
|
||||||
|
# this:
|
||||||
|
#
|
||||||
|
# Add subproject master - master4 - files_subtree/master5 - Empty commit
|
||||||
|
#
|
||||||
|
# where the root commit adds three files: master1.t, master2.t and master3.t.
|
||||||
|
#
|
||||||
|
# This commit history is then rebased onto `master3` with the
|
||||||
|
# `-Xsubtree=files_subtree` option in three different ways:
|
||||||
|
#
|
||||||
|
# 1. using `--preserve-merges`
|
||||||
|
# 2. using `--preserve-merges` and --keep-empty
|
||||||
|
# 3. without specifying a rebase backend
|
||||||
|
|
||||||
test_expect_success 'setup' '
|
test_expect_success 'setup' '
|
||||||
test_commit README &&
|
test_commit README &&
|
||||||
mkdir files &&
|
|
||||||
(
|
git init files &&
|
||||||
cd files &&
|
test_commit -C files master1 &&
|
||||||
git init &&
|
test_commit -C files master2 &&
|
||||||
test_commit master1 &&
|
test_commit -C files master3 &&
|
||||||
test_commit master2 &&
|
|
||||||
test_commit master3
|
: perform subtree merge into files_subtree/ &&
|
||||||
) &&
|
git fetch files refs/heads/master:refs/heads/files-master &&
|
||||||
git fetch files master &&
|
git merge -s ours --no-commit --allow-unrelated-histories \
|
||||||
git branch files-master FETCH_HEAD &&
|
files-master &&
|
||||||
git read-tree --prefix=files_subtree files-master &&
|
git read-tree --prefix=files_subtree -u files-master &&
|
||||||
git checkout -- files_subtree &&
|
git commit -m "Add subproject master" &&
|
||||||
tree=$(git write-tree) &&
|
|
||||||
head=$(git rev-parse HEAD) &&
|
: add two extra commits to rebase &&
|
||||||
rev=$(git rev-parse --verify files-master^0) &&
|
test_commit -C files_subtree master4 &&
|
||||||
commit=$(git commit-tree -p $head -p $rev -m "Add subproject master" $tree) &&
|
test_commit files_subtree/master5 &&
|
||||||
git update-ref HEAD $commit &&
|
|
||||||
(
|
git checkout -b to-rebase &&
|
||||||
cd files_subtree &&
|
git fast-export --no-data HEAD -- files_subtree/ |
|
||||||
test_commit master4
|
sed -e "s%\([0-9a-f]\{40\} \)files_subtree/%\1%" |
|
||||||
) &&
|
git fast-import --force --quiet &&
|
||||||
test_commit files_subtree/master5
|
git reset --hard &&
|
||||||
|
git commit -m "Empty commit" --allow-empty
|
||||||
'
|
'
|
||||||
|
|
||||||
# FAILURE: Does not preserve master4.
|
# FAILURE: Does not preserve master4.
|
||||||
test_expect_failure REBASE_P \
|
test_expect_failure REBASE_P 'Rebase -Xsubtree --preserve-merges --onto commit' '
|
||||||
'Rebase -Xsubtree --preserve-merges --onto commit 4' '
|
|
||||||
reset_rebase &&
|
reset_rebase &&
|
||||||
git checkout -b rebase-preserve-merges-4 master &&
|
git checkout -b rebase-preserve-merges to-rebase &&
|
||||||
git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
|
|
||||||
git commit -m "Empty commit" --allow-empty &&
|
|
||||||
git rebase -Xsubtree=files_subtree --preserve-merges --onto files-master master &&
|
|
||||||
verbose test "$(commit_message HEAD~)" = "files_subtree/master4"
|
|
||||||
'
|
|
||||||
|
|
||||||
# FAILURE: Does not preserve master5.
|
|
||||||
test_expect_failure REBASE_P \
|
|
||||||
'Rebase -Xsubtree --preserve-merges --onto commit 5' '
|
|
||||||
reset_rebase &&
|
|
||||||
git checkout -b rebase-preserve-merges-5 master &&
|
|
||||||
git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
|
|
||||||
git commit -m "Empty commit" --allow-empty &&
|
|
||||||
git rebase -Xsubtree=files_subtree --preserve-merges --onto files-master master &&
|
git rebase -Xsubtree=files_subtree --preserve-merges --onto files-master master &&
|
||||||
|
verbose test "$(commit_message HEAD~)" = "master4" &&
|
||||||
verbose test "$(commit_message HEAD)" = "files_subtree/master5"
|
verbose test "$(commit_message HEAD)" = "files_subtree/master5"
|
||||||
'
|
'
|
||||||
|
|
||||||
# FAILURE: Does not preserve master4.
|
# FAILURE: Does not preserve master4.
|
||||||
test_expect_failure REBASE_P \
|
test_expect_failure REBASE_P 'Rebase -Xsubtree --keep-empty --preserve-merges --onto commit' '
|
||||||
'Rebase -Xsubtree --keep-empty --preserve-merges --onto commit 4' '
|
|
||||||
reset_rebase &&
|
reset_rebase &&
|
||||||
git checkout -b rebase-keep-empty-4 master &&
|
git checkout -b rebase-keep-empty to-rebase &&
|
||||||
git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
|
|
||||||
git commit -m "Empty commit" --allow-empty &&
|
|
||||||
git rebase -Xsubtree=files_subtree --keep-empty --preserve-merges --onto files-master master &&
|
|
||||||
verbose test "$(commit_message HEAD~2)" = "files_subtree/master4"
|
|
||||||
'
|
|
||||||
|
|
||||||
# FAILURE: Does not preserve master5.
|
|
||||||
test_expect_failure REBASE_P \
|
|
||||||
'Rebase -Xsubtree --keep-empty --preserve-merges --onto commit 5' '
|
|
||||||
reset_rebase &&
|
|
||||||
git checkout -b rebase-keep-empty-5 master &&
|
|
||||||
git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
|
|
||||||
git commit -m "Empty commit" --allow-empty &&
|
|
||||||
git rebase -Xsubtree=files_subtree --keep-empty --preserve-merges --onto files-master master &&
|
|
||||||
verbose test "$(commit_message HEAD~)" = "files_subtree/master5"
|
|
||||||
'
|
|
||||||
|
|
||||||
# FAILURE: Does not preserve Empty.
|
|
||||||
test_expect_failure REBASE_P \
|
|
||||||
'Rebase -Xsubtree --keep-empty --preserve-merges --onto empty commit' '
|
|
||||||
reset_rebase &&
|
|
||||||
git checkout -b rebase-keep-empty-empty master &&
|
|
||||||
git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
|
|
||||||
git commit -m "Empty commit" --allow-empty &&
|
|
||||||
git rebase -Xsubtree=files_subtree --keep-empty --preserve-merges --onto files-master master &&
|
git rebase -Xsubtree=files_subtree --keep-empty --preserve-merges --onto files-master master &&
|
||||||
|
verbose test "$(commit_message HEAD~2)" = "master4" &&
|
||||||
|
verbose test "$(commit_message HEAD~)" = "files_subtree/master5" &&
|
||||||
verbose test "$(commit_message HEAD)" = "Empty commit"
|
verbose test "$(commit_message HEAD)" = "Empty commit"
|
||||||
'
|
'
|
||||||
|
|
||||||
# FAILURE: fatal: Could not parse object
|
test_expect_success 'Rebase -Xsubtree --keep-empty --onto commit' '
|
||||||
test_expect_failure 'Rebase -Xsubtree --onto commit 4' '
|
|
||||||
reset_rebase &&
|
reset_rebase &&
|
||||||
git checkout -b rebase-onto-4 master &&
|
git checkout -b rebase-onto to-rebase &&
|
||||||
git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
|
test_must_fail git rebase -Xsubtree=files_subtree --keep-empty --onto files-master master &&
|
||||||
git commit -m "Empty commit" --allow-empty &&
|
: first pick results in no changes &&
|
||||||
git rebase -Xsubtree=files_subtree --onto files-master master &&
|
git rebase --continue &&
|
||||||
verbose test "$(commit_message HEAD~2)" = "files_subtree/master4"
|
verbose test "$(commit_message HEAD~2)" = "master4" &&
|
||||||
|
verbose test "$(commit_message HEAD~)" = "files_subtree/master5" &&
|
||||||
|
verbose test "$(commit_message HEAD)" = "Empty commit"
|
||||||
'
|
'
|
||||||
|
|
||||||
# FAILURE: fatal: Could not parse object
|
test_expect_success 'Rebase -Xsubtree --keep-empty --rebase-merges --onto commit' '
|
||||||
test_expect_failure 'Rebase -Xsubtree --onto commit 5' '
|
|
||||||
reset_rebase &&
|
reset_rebase &&
|
||||||
git checkout -b rebase-onto-5 master &&
|
git checkout -b rebase-merges-onto to-rebase &&
|
||||||
git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
|
test_must_fail git rebase -Xsubtree=files_subtree --keep-empty --rebase-merges --onto files-master --root &&
|
||||||
git commit -m "Empty commit" --allow-empty &&
|
: first pick results in no changes &&
|
||||||
git rebase -Xsubtree=files_subtree --onto files-master master &&
|
git rebase --continue &&
|
||||||
verbose test "$(commit_message HEAD~)" = "files_subtree/master5"
|
verbose test "$(commit_message HEAD~2)" = "master4" &&
|
||||||
'
|
verbose test "$(commit_message HEAD~)" = "files_subtree/master5" &&
|
||||||
# FAILURE: fatal: Could not parse object
|
|
||||||
test_expect_failure 'Rebase -Xsubtree --onto empty commit' '
|
|
||||||
reset_rebase &&
|
|
||||||
git checkout -b rebase-onto-empty master &&
|
|
||||||
git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
|
|
||||||
git commit -m "Empty commit" --allow-empty &&
|
|
||||||
git rebase -Xsubtree=files_subtree --onto files-master master &&
|
|
||||||
verbose test "$(commit_message HEAD)" = "Empty commit"
|
verbose test "$(commit_message HEAD)" = "Empty commit"
|
||||||
'
|
'
|
||||||
|
|
||||||
|
@ -441,4 +441,25 @@ test_expect_success '--continue after resolving conflicts after a merge' '
|
|||||||
test_path_is_missing .git/MERGE_HEAD
|
test_path_is_missing .git/MERGE_HEAD
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success '--rebase-merges with strategies' '
|
||||||
|
git checkout -b with-a-strategy F &&
|
||||||
|
test_tick &&
|
||||||
|
git merge -m "Merge conflicting-G" conflicting-G &&
|
||||||
|
|
||||||
|
: first, test with a merge strategy option &&
|
||||||
|
git rebase -ir -Xtheirs G &&
|
||||||
|
echo conflicting-G >expect &&
|
||||||
|
test_cmp expect G.t &&
|
||||||
|
|
||||||
|
: now, try with a merge strategy other than recursive &&
|
||||||
|
git reset --hard @{1} &&
|
||||||
|
write_script git-merge-override <<-\EOF &&
|
||||||
|
echo overridden$1 >>G.t
|
||||||
|
git add G.t
|
||||||
|
EOF
|
||||||
|
PATH="$PWD:$PATH" git rebase -ir -s override -Xxopt G &&
|
||||||
|
test_write_lines G overridden--xopt >expect &&
|
||||||
|
test_cmp expect G.t
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Reference in New Issue
Block a user