Subject: Re: git merge branch --no-commit does commit fast forward merges

From: Junio C Hamano <[email-masked]>
Date: Mon, 18 Apr 2016 09:36:30 -0700

Andrew Ardill <[email-masked]> writes:

> Yes, I think the mis-alignment in expectations comes from a
> technicality in the description you quote. The fast forward is in some
> ways not really counted as a true merge, and no new commits are
> created.

Looking at 123ee3ca (Add --no-commit to git-merge/git-pull.,
2005-11-01) and $gmane/10998 [*1*], it is clear that "--no-commit"
was never meant as a "preview of what would happen".  The original
documentation update at 37465016 (Documentation: -merge and -pull:
describe merge strategies., 2005-11-04) was not great, but was
clarified at d8ae1d10 (Document the --no-commit flag better,
2005-11-04), and that version of text survives to this day.

The real reason why "--no-commit" was added was because back then
"git commit --amend" did not even exist; it appeared only at
b4019f04 (git-commit --amend, 2006-03-02).

What is (and was back then) the recommended way to see what changes
merging the other branch brings in to your branch, then?

There are at least three ways, all of which are better suited than
"--no-commit".

When you want to study and understand what changes other branch 
made since it forked from what you are working on, then

    $ git diff ...other_branch

would give you the change as a single ball of wax [*2*].

If you want to see individual changes explained by their authors,
you can also do

    $ git log -p ..other_branch

Finally, if you want to see what the merge result would look like,
you just do the merge.  Advancing the HEAD by one commit and then
going back once you are done is a cheap operation.  If you want to
avoid updating your branch for real, these days you can even do so
on a detached HEAD, unlike old days back when there was not even
"commit --amend".

    $ git checkout HEAD^0
    $ git merge other_branch

    $ git diff ORIG_HEAD     ;# what changed overall?
    $ git log -p ORIG_HEAD.. ;# inspect individual changes

    $ git checkout - ;# come back to the original branch

> I do think that the --no-commit option should imply --no-ff (as this
> would make the behaviour consistent for end-users). I don't know if
> this is something that would break scripts etc, but if so you could
> make it implied only if we detect a terminal or something like is done
> in other places.

If we were living in an ideal world where "git commit --amend" were
already there in November 2005, we wouldn't have "merge --no-commit"
or "pull --no-commit" in our system today, and in such a world, I
would agree that "try to populate the working tree and the index
with result of a hypothetical merge and stop without updating HEAD
nor creating MERGE_HEAD, only to show what would happen if I merged"
option could be a useful addition to these two commands.  And we may
choose to call such an option "--no-commit".  I agree that such an
option should probably imply "--no-ff".

But we are not living in that world.  Making "--no-commit" (which is
not that "try to populate and show" command) imply "--no-ff" will
break existing scripts.  And unlike cosmetic things like "do we show
in color", changing the behaviour of a command in a fundamental way
based on term and istty() is a sure way to make commands harder to
understand ("it works this way from the terminal, but it works
differently in my script. what is going on?"  is not a question we
are better off not seeing on this list).

Thanks.

[Notes and References]

*1* http://thread.gmane.org/gmane.comp.version-control.git/10998 

*2* Notice the three dots; it is a short-hand for

    $ git diff ^$(git merge-base HEAD other_branch) other_branch