git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: colin@horizon.com
Cc: hvammen@gmail.com, git@vger.kernel.org
Subject: Re: [RFC/PATCH] Fast forward strategies allow, never, and only
Date: Tue, 11 Mar 2008 18:57:20 -0700	[thread overview]
Message-ID: <7v1w6gbt6n.fsf@gitster.siamese.dyndns.org> (raw)
In-Reply-To: <20080311093553.23191.qmail@science.horizon.com> (colin@horizon.com's message of "Tue, 11 Mar 2008 05:35:53 -0400")

colin@horizon.com writes:

>      a--a--a
>     /       \
> o--o         o---o <-- A's head
>     \       / \ /
>      b--b--b---o <-- B's head
>
>      a--a--a
>     /       \
> o--o         o---o <-- A's head
>     \       / \ / \
>      b--b--b---o---o <-- B's head
>
> .. and it never ends.  All of the merged commits are identical trees, but
> if you insist on creating a new commit object each time, you can generate
> an infinite number of bogus commits, and more to the point, A and B will
> never actually agree on the current HEAD commit.
>
> With more developers, you can make even more of a mess.
>
> What use does the "--ff=never" option have except to generate this cruft?

Judicious use of non-fast-forward has a justification that is not too
unreasonable.  That is, when you want to treat one lineage of history as
"more special than others".

If your workflow is always to branch from the special branch ("master")
when working on even a miniscule topic and merge that back to "master", if
you happen to have worked only on a single topic and the "master" was
never advanced during the time you worked on that topic, merging the topic
back to "master" will result in a fast-forward.  When you look back that
history, you won't be able to tell where the topic started and ended by
following the ancestry chain of the "master" branch.

Using "never fast forward" policy on such a special branch will be a way
to make sure that all commits on the first-parent ancestry of that special
branch will be merges from something else, and by computing $it^1..$it^2
for a merge commit $it on the special branch, which merges the topic fully
into it, you can tell what commits the topic consisted of.

When you have repeated merges from a topic to that special branch, this
computation needs to be a bit more than just $it^1..$it^2 of the last
merge commit that merges the topic into "master".  E.g. you would have two
"should have been fast forward but artificially made into a real merge for
the purpose of peeing in the snow" like this:

           o---o---o---o---o "topic"
          /     \           \
      ---o-------*-----------* "master"
 
By following the first-parent ancestry of "master", you can tell that the
first two changes on "topic" were accepted earlier and then three fixups
on top were incorporated much later, which is not something you can do if
you allowed fast-forward merge into "master".  Computing this history is
somewhat expensive but it is doable.  You have to follow the commit
ancestry of "topic", and for each commit you find, you would need to see
which commit on the first-parent ancestry of "master" can reach it
(e.g. the three topmost ones on "topic" can be reachable only by the last
merge on "master", while the remaining two can be reached by the previous
merge on "master").

In other words, if there is a globally special "master" history where
everybody meets, forcing an artificial merge can have value.  However, for
this to work, you can never commit anything directly on such a special
"master" branch, because directly committing on "master" is equivalent to
fork a small topic branch that has a single commit on it, and immediately
merging it back with a fast-forward merge to "master".  So an artificial
merge can have value but that value can be had only with a disciplined
workflow.

Last night I pulled a topic from Shawn which was a series of updates to
the bash completion script.  It was based on the tip of 'master' and
resulted in a fast forward.  In git.git circle, it happens that my
"master" history is not special at all.  I have "trivially correct fixups"
directly committed on "master" all the time, and fast-forwarding to the
tip of bash completion updates Shawn collected for me was exactly that,
with only different committer.  So even though I act as the top-level
integrator for git.git history, there was no reason to do non-fast-forward
merge at that point.  My tree is not that special.

On the other hand, I probably _could_ use non-ff to manage "next", which
will fork off of the tip of "master" after every major release.  In order
to treat the first topic that will be merged into "next" just like other
later topics, it should be merged without fast-forward.  The latter topics
will never fast-forward (because topics fork off of "master" or "maint"
and never from "next" itself) but the very first one can (because "master"
and "next" will be at the same at that point), and allowing fast-forward
would mean the first topic after a major release is treated differently
from others.  This is possible only because there is a fairly strict
discipline of not committing anything directly on top of "next" and not
forking off of it.

  parent reply	other threads:[~2008-03-12  1:58 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-11  9:35 [RFC/PATCH] Fast forward strategies allow, never, and only colin
2008-03-11 10:09 ` Lars Hjemli
2008-03-11 12:24 ` Bruce Stephens
2008-03-11 12:33   ` Bruce Stephens
2008-03-12  1:57 ` Junio C Hamano [this message]
  -- strict thread matches above, loose matches on Subject: below --
2008-03-11  2:59 Sverre Hvammen Johansen
2008-03-11  3:18 ` Sverre Hvammen Johansen
2008-03-11  5:17   ` Ping Yin
2008-03-11  6:19 ` Junio C Hamano
2008-03-12  5:46   ` Sverre Hvammen Johansen
2008-03-16  6:44     ` Sverre Hvammen Johansen
2008-03-14  2:35   ` Sverre Hvammen Johansen
2008-03-11  9:15 ` Jakub Narebski
2008-03-12  4:24   ` Sverre Hvammen Johansen
2008-03-12  4:50     ` Junio C Hamano
2008-03-12  5:51       ` Sverre Hvammen Johansen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7v1w6gbt6n.fsf@gitster.siamese.dyndns.org \
    --to=gitster@pobox.com \
    --cc=colin@horizon.com \
    --cc=git@vger.kernel.org \
    --cc=hvammen@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).