Merge branch 'fc/pull-merge-rebase'
When a user does not tell "git pull" to use rebase or merge, the command gives a loud message telling a user to choose between rebase or merge but creates a merge anyway, forcing users who would want to rebase to redo the operation. Fix an early part of this problem by tightening the condition to give the message---there is no reason to stop or force the user to choose between rebase or merge if the history fast-forwards. * fc/pull-merge-rebase: pull: display default warning only when non-ff pull: correct condition to trigger non-ff advice pull: get rid of unnecessary global variable pull: give the advice for choosing rebase/merge much later pull: refactor fast-forward check
This commit is contained in:
commit
d3fa84d528
@ -324,7 +324,7 @@ static const char *config_get_ff(void)
|
||||
* looks for the value of "pull.rebase". If both configuration keys do not
|
||||
* exist, returns REBASE_FALSE.
|
||||
*/
|
||||
static enum rebase_type config_get_rebase(void)
|
||||
static enum rebase_type config_get_rebase(int *rebase_unspecified)
|
||||
{
|
||||
struct branch *curr_branch = branch_get("HEAD");
|
||||
const char *value;
|
||||
@ -344,20 +344,7 @@ static enum rebase_type config_get_rebase(void)
|
||||
if (!git_config_get_value("pull.rebase", &value))
|
||||
return parse_config_rebase("pull.rebase", value, 1);
|
||||
|
||||
if (opt_verbosity >= 0 && !opt_ff) {
|
||||
advise(_("Pulling without specifying how to reconcile divergent branches is\n"
|
||||
"discouraged. You can squelch this message by running one of the following\n"
|
||||
"commands sometime before your next pull:\n"
|
||||
"\n"
|
||||
" git config pull.rebase false # merge (the default strategy)\n"
|
||||
" git config pull.rebase true # rebase\n"
|
||||
" git config pull.ff only # fast-forward only\n"
|
||||
"\n"
|
||||
"You can replace \"git config\" with \"git config --global\" to set a default\n"
|
||||
"preference for all repositories. You can also pass --rebase, --no-rebase,\n"
|
||||
"or --ff-only on the command line to override the configured default per\n"
|
||||
"invocation.\n"));
|
||||
}
|
||||
*rebase_unspecified = 1;
|
||||
|
||||
return REBASE_FALSE;
|
||||
}
|
||||
@ -924,6 +911,36 @@ static int run_rebase(const struct object_id *newbase,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_can_ff(struct object_id *orig_head, struct object_id *orig_merge_head)
|
||||
{
|
||||
int ret;
|
||||
struct commit_list *list = NULL;
|
||||
struct commit *merge_head, *head;
|
||||
|
||||
head = lookup_commit_reference(the_repository, orig_head);
|
||||
commit_list_insert(head, &list);
|
||||
merge_head = lookup_commit_reference(the_repository, orig_merge_head);
|
||||
ret = repo_is_descendant_of(the_repository, merge_head, list);
|
||||
free_commit_list(list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void show_advice_pull_non_ff(void)
|
||||
{
|
||||
advise(_("Pulling without specifying how to reconcile divergent branches is\n"
|
||||
"discouraged. You can squelch this message by running one of the following\n"
|
||||
"commands sometime before your next pull:\n"
|
||||
"\n"
|
||||
" git config pull.rebase false # merge (the default strategy)\n"
|
||||
" git config pull.rebase true # rebase\n"
|
||||
" git config pull.ff only # fast-forward only\n"
|
||||
"\n"
|
||||
"You can replace \"git config\" with \"git config --global\" to set a default\n"
|
||||
"preference for all repositories. You can also pass --rebase, --no-rebase,\n"
|
||||
"or --ff-only on the command line to override the configured default per\n"
|
||||
"invocation.\n"));
|
||||
}
|
||||
|
||||
int cmd_pull(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
const char *repo, **refspecs;
|
||||
@ -931,6 +948,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
|
||||
struct object_id orig_head, curr_head;
|
||||
struct object_id rebase_fork_point;
|
||||
int autostash;
|
||||
int rebase_unspecified = 0;
|
||||
int can_ff;
|
||||
|
||||
if (!getenv("GIT_REFLOG_ACTION"))
|
||||
set_reflog_message(argc, argv);
|
||||
@ -952,7 +971,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
|
||||
opt_ff = xstrdup_or_null(config_get_ff());
|
||||
|
||||
if (opt_rebase < 0)
|
||||
opt_rebase = config_get_rebase();
|
||||
opt_rebase = config_get_rebase(&rebase_unspecified);
|
||||
|
||||
if (read_cache_unmerged())
|
||||
die_resolve_conflict("pull");
|
||||
@ -1026,6 +1045,13 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
|
||||
if (opt_rebase && merge_heads.nr > 1)
|
||||
die(_("Cannot rebase onto multiple branches."));
|
||||
|
||||
can_ff = get_can_ff(&orig_head, &merge_heads.oid[0]);
|
||||
|
||||
if (rebase_unspecified && !opt_ff && !can_ff) {
|
||||
if (opt_verbosity >= 0)
|
||||
show_advice_pull_non_ff();
|
||||
}
|
||||
|
||||
if (opt_rebase) {
|
||||
int ret = 0;
|
||||
int ran_ff = 0;
|
||||
@ -1040,22 +1066,12 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
|
||||
submodule_touches_in_range(the_repository, &upstream, &curr_head))
|
||||
die(_("cannot rebase with locally recorded submodule modifications"));
|
||||
if (!autostash) {
|
||||
struct commit_list *list = NULL;
|
||||
struct commit *merge_head, *head;
|
||||
|
||||
head = lookup_commit_reference(the_repository,
|
||||
&orig_head);
|
||||
commit_list_insert(head, &list);
|
||||
merge_head = lookup_commit_reference(the_repository,
|
||||
&merge_heads.oid[0]);
|
||||
if (repo_is_descendant_of(the_repository,
|
||||
merge_head, list)) {
|
||||
if (can_ff) {
|
||||
/* we can fast-forward this without invoking rebase */
|
||||
opt_ff = "--ff-only";
|
||||
ran_ff = 1;
|
||||
ret = run_merge();
|
||||
}
|
||||
free_commit_list(list);
|
||||
}
|
||||
if (!ran_ff)
|
||||
ret = run_rebase(&newbase, &upstream);
|
||||
|
@ -29,11 +29,8 @@ test_expect_success 'setup' '
|
||||
|
||||
test_expect_success 'pull.rebase not set' '
|
||||
git reset --hard c0 &&
|
||||
git -c color.advice=always pull . c1 2>err &&
|
||||
test_decode_color <err >decoded &&
|
||||
test_i18ngrep "<YELLOW>hint: " decoded &&
|
||||
test_i18ngrep "Pulling without specifying how to reconcile" decoded
|
||||
|
||||
git pull . c1 2>err &&
|
||||
test_i18ngrep ! "Pulling without specifying how to reconcile" err
|
||||
'
|
||||
|
||||
test_expect_success 'pull.rebase not set and pull.ff=true' '
|
||||
@ -87,6 +84,65 @@ test_expect_success 'pull.rebase not set and --ff-only given' '
|
||||
test_i18ngrep ! "Pulling without specifying how to reconcile" err
|
||||
'
|
||||
|
||||
test_expect_success 'pull.rebase not set (not-fast-forward)' '
|
||||
git reset --hard c2 &&
|
||||
git -c color.advice=always pull . c1 2>err &&
|
||||
test_decode_color <err >decoded &&
|
||||
test_i18ngrep "<YELLOW>hint: " decoded &&
|
||||
test_i18ngrep "Pulling without specifying how to reconcile" decoded
|
||||
'
|
||||
|
||||
test_expect_success 'pull.rebase not set and pull.ff=true (not-fast-forward)' '
|
||||
git reset --hard c2 &&
|
||||
test_config pull.ff true &&
|
||||
git pull . c1 2>err &&
|
||||
test_i18ngrep ! "Pulling without specifying how to reconcile" err
|
||||
'
|
||||
|
||||
test_expect_success 'pull.rebase not set and pull.ff=false (not-fast-forward)' '
|
||||
git reset --hard c2 &&
|
||||
test_config pull.ff false &&
|
||||
git pull . c1 2>err &&
|
||||
test_i18ngrep ! "Pulling without specifying how to reconcile" err
|
||||
'
|
||||
|
||||
test_expect_success 'pull.rebase not set and pull.ff=only (not-fast-forward)' '
|
||||
git reset --hard c2 &&
|
||||
test_config pull.ff only &&
|
||||
test_must_fail git pull . c1 2>err &&
|
||||
test_i18ngrep ! "Pulling without specifying how to reconcile" err
|
||||
'
|
||||
|
||||
test_expect_success 'pull.rebase not set and --rebase given (not-fast-forward)' '
|
||||
git reset --hard c2 &&
|
||||
git pull --rebase . c1 2>err &&
|
||||
test_i18ngrep ! "Pulling without specifying how to reconcile" err
|
||||
'
|
||||
|
||||
test_expect_success 'pull.rebase not set and --no-rebase given (not-fast-forward)' '
|
||||
git reset --hard c2 &&
|
||||
git pull --no-rebase . c1 2>err &&
|
||||
test_i18ngrep ! "Pulling without specifying how to reconcile" err
|
||||
'
|
||||
|
||||
test_expect_success 'pull.rebase not set and --ff given (not-fast-forward)' '
|
||||
git reset --hard c2 &&
|
||||
git pull --ff . c1 2>err &&
|
||||
test_i18ngrep ! "Pulling without specifying how to reconcile" err
|
||||
'
|
||||
|
||||
test_expect_success 'pull.rebase not set and --no-ff given (not-fast-forward)' '
|
||||
git reset --hard c2 &&
|
||||
git pull --no-ff . c1 2>err &&
|
||||
test_i18ngrep ! "Pulling without specifying how to reconcile" err
|
||||
'
|
||||
|
||||
test_expect_success 'pull.rebase not set and --ff-only given (not-fast-forward)' '
|
||||
git reset --hard c2 &&
|
||||
test_must_fail git pull --ff-only . c1 2>err &&
|
||||
test_i18ngrep ! "Pulling without specifying how to reconcile" err
|
||||
'
|
||||
|
||||
test_expect_success 'merge c1 with c2' '
|
||||
git reset --hard c1 &&
|
||||
test -f c0.c &&
|
||||
|
Loading…
Reference in New Issue
Block a user