Fred Stluka on 21 Dec 2018 22:50:24 -0800


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: [PLUG] Git: net time gain or loss?


Rich,

Hmmm...  OK.  I've never gotten in the habit of rebasing.  The parallel
branches of the merge commits have always made perfect sense to
me.  Seems to fit the reality of what happened better.  The rebased
history DOES seem to me like re-writing history.  I remember now
that someone on a project a few years back was encouraging rebases.
But he was solving a problem that I felt we didn't have, so I could
never understand why we would bother.

Thanks for the explanation and the Gentoo link!

--Fred
------------------------------------------------------------------------
Fred Stluka -- Bristle Software, Inc. -- http://bristle.com
#DontBeATrump -- Make America Honorable Again!
------------------------------------------------------------------------

On 12/21/18 6:09 PM, Rich Freeman wrote:
On Fri, Dec 21, 2018 at 5:02 PM Fred Stluka <fred@bristle.com> wrote:
On 12/20/18 9:23 PM, Aaron Mulder wrote:
But those merge commits are dang ugly, and rebase seems to be a clever
option to avoid that... granted one that can be a big headache to
understand and adjusts the history a bit and could be completely
unnecessary if not for the distributed nature of the thing.
Merge commits are fine, I think.  Merge conflicts are a pain, but
are you saying that all merge commits are ugly.  Why?

Also, how does rebase help?  A couple people have said that now,
so I must be missing something.  Enlighten me?

So, this is a somewhat religious topic.

When using rebase you get a linear-ized history, as if every commit
was made against the one coming before.  When using a merge you get a
branching history, whether those branches were explicit or implicit.

Let me give an example from Gentoo, formatted using tig.  Here is our
main development repository where almost all commits are rebased:
2018-12-20 22:56 Matthew Thode                             o [master]
{origin/master} {github/master} {origin/HEAD} app-admin/puppet:
4.10.12 stable amd64 and x86 with cleanup
2018-12-20 22:55 Matthew Thode                             o
www-apps/icingaweb2: 2.6.2 stable amd64 and x86
2018-12-20 20:16 Georgy Yakovlev                           o
app-shells/mcfly: fix typo in postinst message
2018-12-20 20:11 Georgy Yakovlev                           o
dev-python/pyTenable: drop old
2018-12-20 20:10 Georgy Yakovlev                           o
dev-python/pyTenable: bump to 0.3.7
2018-12-20 21:17 Anthony G. Basile                         o
net-vpn/tor: remove older stable version
2018-12-20 21:16 Anthony G. Basile                         o
net-vpn/tor: remove older alphas
2018-12-20 21:15 Anthony G. Basile                         o
net-vpn/tor: version bump to 0.3.5.6_rc
2018-12-20 17:41 Patrick McLean                            o
virtual/cargo: Version bump to 1.31.1
2018-12-20 17:41 Patrick McLean                            o
virtual/rust: Version bump to 1.31.1

Now, here is a similar repository after it goes through a layer of CI
that does some QA to ensure only passing commits end up on time.  It
fetches and merges groups of commits, adding some extra stuff and
signatures to the history:
2018-12-21 05:04 Repository mirror & CI                    o [stable]
{origin/stable} {origin/HEAD} 2018-12-21 05:04:21 UTC
2018-12-21 05:04 Repository mirror & CI                    M─┐ Merge
updates from master
2018-12-20 22:56 Matthew Thode                             │ o
app-admin/puppet: 4.10.12 stable amd64 and x86 with cleanup
2018-12-20 22:55 Matthew Thode                             │ o
www-apps/icingaweb2: 2.6.2 stable amd64 and x86
2018-12-21 04:24 Repository mirror & CI                    o │
2018-12-21 04:24:16 UTC
2018-12-21 04:23 Repository mirror & CI                    M─│─┐ Merge
updates from master
2018-12-20 20:16 Georgy Yakovlev                           │ o─┘
app-shells/mcfly: fix typo in postinst message
2018-12-20 20:11 Georgy Yakovlev                           │ o
dev-python/pyTenable: drop old
2018-12-20 20:10 Georgy Yakovlev                           │ o
dev-python/pyTenable: bump to 0.3.7
2018-12-21 02:24 Repository mirror & CI                    o │
2018-12-21 02:24:18 UTC
2018-12-21 02:24 Repository mirror & CI                    M─│─┐ Merge
updates from master
2018-12-20 21:17 Anthony G. Basile                         │ o─┘
net-vpn/tor: remove older stable version
2018-12-20 21:16 Anthony G. Basile                         │ o
net-vpn/tor: remove older alphas
2018-12-20 21:15 Anthony G. Basile                         │ o
net-vpn/tor: version bump to 0.3.5.6_rc
2018-12-21 02:04 Repository mirror & CI                    o │
2018-12-21 02:04:24 UTC

(you'll want to use a monospaced font to view all that)

What starts out as a completely linear history gets turned into these
two dovetailing merged histories which are harder to follow.

When there really is parallel development going on then the merges
capture information about the actual history of the repository.
However, when you really have a linear flow with just one-off commits
happening in parallel you get these merge commits everywhere that
makes it harder to traverse the history.

If you want to do an automated traversal of the repository commit
history this is trivial with rebasing, and more complex with merges.
Which parent is the "real" one?

Gentoo discussed this at length and documented its policy as follows
(which I think is pretty typical):
https://www.gentoo.org/glep/glep-0066.html#merge-commits

The use of merge commits in the Gentoo repository is strongly
discouraged. Usually it is preferable to rebase instead. However, the
developers are allowed to use merge commits in justified cases. Merge
commits can be only used to merge additional branches, the use of
implicit git pull merges is entirely forbidden.

In a merge commit that is committed straight to the Gentoo repository,
the first parent is expected to reference an actual Gentoo commit
preceding the merge, while the remaining parents can be used to
reference commits originating from external repositories. The commits
on the ancestry path of the first parent (up to the next merge
commit) are required to conform to this specification. The commits on
remaining ancestry paths can use relaxed rules.
In the case of a genuine branching workflow, where you create a
feature branch, QA it, and then merge it, the merge commit is
completely appropriate and clearly reflects the actual development
history.

Now, one thing people dislike about rebasing is that it "rewrites
history."  This isn't to say that it actually CHANGES history - git
history is completely immutable.  It creates a new copy of history,
distinct from the old one, which might still continue to exist.
Indeed, if you're using gpg signatures in your repository then these
signatures will be lost in the new history, or substituted with new
ones (which obviously requires the appropriate signing key).  Commit
2914c180223 will always be what it always was - it just may or may not
end up in the branch that actually gets further used.

Strictly speaking though there is nothing wrong with merge commits.
It is a matter of opinion as to whether the additional information
they preserve is actually useful, or clutter.


___________________________________________________________________________
Philadelphia Linux Users Group         --        http://www.phillylinux.org
Announcements - http://lists.phillylinux.org/mailman/listinfo/plug-announce
General Discussion  --   http://lists.phillylinux.org/mailman/listinfo/plug