Skip to content

Commit

Permalink
Improve hint for diverging branches.
Browse files Browse the repository at this point in the history
Added a description of what the offered options will do and also
offered a 3rd during pull - a hard reset.
This option should be helpful for the new users that accidentally
committed into the wrong branch.

There is some danger because it's semi-destructive, but so are
other options offered if user doesn't know the commands,
additionally I think "To discard your local changes" wording
describes this clearly enough.

Signed-off-by: Konstantin Pereiaslov <perk11@perk11.info>
  • Loading branch information
perk11 committed Sep 4, 2023
1 parent d814540 commit 237f897
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 9 deletions.
3 changes: 2 additions & 1 deletion Documentation/config/advice.txt
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ advice.*::
is asked to update index entries outside the current sparse
checkout.
diverging::
Advice shown when a fast-forward is not possible.
Advice shown when a fast-forward is not possible during merge
or pull operation.
worktreeAddOrphan::
Advice shown when a user tries to create a worktree from an
invalid reference, to instruct how to create a new orphan
Expand Down
27 changes: 23 additions & 4 deletions advice.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,19 +220,38 @@ void NORETURN die_conclude_merge(void)
die(_("Exiting because of unfinished merge."));
}

void NORETURN die_ff_impossible(void)
void NORETURN die_ff_impossible_during_merge(void)
{
advise_if_enabled(ADVICE_DIVERGING,
_("Diverging branches can't be fast-forwarded, you need to either:\n"
_("Diverging branches can't be fast-forwarded."
"Consider the following options:\n"
"\n"
"To merge remote changes into your branch:\n"
"\tgit merge --no-ff\n"
"\n"
"or:\n"
"\n"
"To apply your changes on top of remote changes:\n"
"\tgit rebase\n"));
die(_("Not possible to fast-forward, aborting."));
}

void NORETURN die_ff_impossible_during_pull(const char *upstream_branch_spec)
{
advise_if_enabled(ADVICE_DIVERGING,
_("Diverging branches can't be fast-forwarded. "
"Consider the following options:\n"
"\n"
"To merge remote changes into your branch:\n"
"\tgit merge --no-ff\n"
"\n"
"To apply your changes on top of remote changes:\n"
"\tgit rebase\n"
"\n"
"To discard your local changes and apply the remote changes:\n"
"\tgit reset --hard %s\n"), upstream_branch_spec);
die(_("Not possible to fast-forward, aborting."));
}


void advise_on_updating_sparse_paths(struct string_list *pathspec_list)
{
struct string_list_item *item;
Expand Down
3 changes: 2 additions & 1 deletion advice.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ void advise_if_enabled(enum advice_type type, const char *advice, ...);
int error_resolve_conflict(const char *me);
void NORETURN die_resolve_conflict(const char *me);
void NORETURN die_conclude_merge(void);
void NORETURN die_ff_impossible(void);
void NORETURN die_ff_impossible_during_merge(void);
void NORETURN die_ff_impossible_during_pull(const char *upstream_branch_spec);
void advise_on_updating_sparse_paths(struct string_list *pathspec_list);
void detach_advice(const char *new_name);
void advise_on_moving_dirty_path(struct string_list *pathspec_list);
Expand Down
2 changes: 1 addition & 1 deletion builtin/merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -1675,7 +1675,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
}

if (fast_forward == FF_ONLY)
die_ff_impossible();
die_ff_impossible_during_merge();

if (autostash)
create_autostash(the_repository,
Expand Down
20 changes: 18 additions & 2 deletions builtin/pull.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,20 @@ static const char *get_tracking_branch(const char *remote, const char *refspec)
refspec_item_clear(&spec);
return merge_branch;
}
/**
* Returns the branch the pull is performed from.
* If remote is NULL or refspec is NULL, configured upstream remote of the current branch is used.
* If refspec is NULL, the current configured upstream branch is used.
*/
static const char *get_pull_branch(const char *remote, const char *refspec)
{
if (refspec == NULL || remote == NULL)
{
return get_upstream_branch(remote);
}

return get_tracking_branch(remote, refspec);
}

/**
* Given the repo and refspecs, sets fork_point to the point at which the
Expand Down Expand Up @@ -1112,8 +1126,10 @@ int cmd_pull(int argc, const char **argv, const char *prefix)

/* ff-only takes precedence over rebase */
if (opt_ff && !strcmp(opt_ff, "--ff-only")) {
if (divergent)
die_ff_impossible();
if (divergent) {
const char* pull_branch_spec = get_pull_branch(repo, *refspecs);
die_ff_impossible_during_pull( pull_branch_spec);
}
opt_rebase = REBASE_FALSE;
}
/* If no action specified and we can't fast forward, then warn. */
Expand Down

0 comments on commit 237f897

Please sign in to comment.