Web lists-archives.com

Re: could `git merge --no-ff origin/master` be made more useful?

On Mon, May 14 2018, demerphq wrote:

> The first time I tried to use --no-ff I tried to do something like this:
>   git checkout master
>   git commit -a -m'whatever'
>   git commit -a -m'whatever2'
>   git merge --no-ff origin/master
> and was disappointed when "it didn't work" and git told me there was
> nothing to do as the branch was up to date. (Which I found a bit
> confusing.)
> I realize now my expectations were incorrect, and that the argument to
> merge needs to resolve to a commit that is ahead of the current
> commit, and in the above sequence it is the other way around. So to do
> what I want I can do:
>   git checkout master
>   git checkout -b topic
>   git commit -a -m'whatever'
>   git commit -a -m'whatever2'
>   git checkout master
>   git merge --no-ff topic
> and iiuir this works because 'master' would be behind 'topic' in this case.
> But I have a few questions, 1) is there is an argument to feed to git
> merge to make the first recipe work like the second? And 2) is this
> asymmetry necessary with --no-ff?

I've been bitten my this myself, but found that it's documented as the
very first thing in git-merge:

    Incorporates changes from the named commits (since the time their
    histories diverged from the current branch) into the current

Since origin/master hasn't diverged from your current branch (unlike the
other way around), the merge with --no-ff is a noop.

> More specifically would something horrible break if --no-ff
> origin/trunk detected that the current branch was ahead of the named
> branch and "swapped"  the implicit order of the two so that the first
> recipe could behave like the second

If it worked like that then the user who sets merge.ff=false in his
config and issues a "git pull" after making a commit on his local master
would create a merge commit.

This old E-Mail of Junio's discusses that edge case & others in detail:

> Anyway, even if the above makes no sense, would it be hard to make the
> message provided by git merge in the first recipe a bit more
> suggestive of what is going on? For instance if it had said "Cannot
> --no-ff merge, origin/master is behind master" it would have been much
> more clear what was going on.

I can't spot any reason for why we couldn't have something like this POC
(would be properly done through advice.c):

    diff --git a/builtin/merge.c b/builtin/merge.c
    index 9db5a2cf16..920f67d9f8 100644
    --- a/builtin/merge.c
    +++ b/builtin/merge.c
    @@ -1407,6 +1407,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                     * but first the most common case of merging one remote.
                    finish_up_to_date(_("Already up to date."));
    +               if (fast_forward == FF_NO)
    +                       fprintf(stderr, "did you mean this the other way around?\n");
                    goto done;
            } else if (fast_forward != FF_NO && !remoteheads->next &&
                            !common->next &&

But that should probably be reworked to be smart about whether --no-ff
or merge.ff=false was specified, i.e. do we want to yell this at the
user who's just set that at his config default, or the user who's
specified --no-ff explicitly, or both? I don't know.