emacs-devel
[Top][All Lists]
Advanced

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

Re: What a modern collaboration toolkit looks like


From: Giorgos Keramidas
Subject: Re: What a modern collaboration toolkit looks like
Date: Thu, 3 Jan 2008 03:08:08 +0200

On 2008-01-02 04:53, Richard Stallman <address@hidden> wrote:
>     You can commit a change offline (git commit).  Later on,
>     when you are online, you say `git pull' to get the current
>     state of the repository, and automatical merging happens
>     (and the usual warnings if there are conflicts).  Finally,
>     you say `git push' to synchronize your git repository with
>     the global one.
>
> Is this substantially different from CVS, or is it just
> relabeling?  It sounds like `git push' is basically equivalent
> to CVS commit.

Yes, there is a substantial difference between committing in a
distributed SCM like Git, and Mercurial (the latter is the one I
am most familiar with).

A commit `attaches' a changeset to a `parent changeset', forming
a changeset graph instead of a linear history.  So if I pull from
the central Emacs repository the changes:

    [1]---[2]---[3]

and start committing on top of this, I will end up with a local
history like this:

    [1]---[2]---[3]---[4]---[5]---[6]

In the mean time, other people have the chance to commit their
own changes to the central tree, on top of the original [3]
changeset.  When I finish my work, and I `pull' from the central
tree again, the local Git history becomes:

                  ,---[7]---[8]
                 /
    [1]---[2]---[3]---[4]---[5]---[6]

A major difference in this sort of history is that *all* changes
have been safely stashed away in the local history.  The working
area of the repository/workspace can, for all intents and
purposes, be considered volatile and completely unimporant.

Having this sort of local history, I can `check out' any one of
the committed changes.  Looking at the `remote' changes I just
pulled is possible with normal `update' commands in Mercurial (a
similar command is available in Git).  This means that switching
between the `local' version and the `remote' version of the code
is as easy as:

    hg update --clean 8               ; remote version is checked out

    hg update --clean 6               ; local version is checked out

The usual commands, like `diff' also work, i.e.:

    hg diff -r 6:8                    ; look at 6 -> 8 patch

    hg diff -r 8:6                    ; look at the inverse patch

Note that a `merge' has not happened yet.  If the remote head of
the history tree looks easy enough to merge, a merge operation
can be done in two ways:

    1) Merging of the two heads, to forma history graph like:

                       ,---[7]---[8]---------[9]
                      /                      /
         [1]---[2]---[3]---[4]---[5]---[6]--'

    2) A `rebase' operation, which restores the linear history of
       the remote branch, and `rebases' all the local changesets
       on top of the remote branch:

         [1]---[2]---[3]---[7]---[8] - - - [4']---[5']---[6']

> With CVS, until you commit your changes, new changes can be
> installed in the repository, and when you DO get around to
> committing your changes, you will have to merge them with
> whatever others have installed.  Once you commit, others trying
> to commit will have the burden of merging their changes with
> your already-committed changes.

The main ease of use from the distributed SCM systems is a result
of the different from the workflow you just described.  With CVS
committers are encouraged to avoid committing local changes,
until a future moment when ``the patch will be done and fully
working''.  When they reach that future point, the onus of the
merging falls on the person who wants to commit.

With a distributed SCM system, committing is not so `scary'.
It's ok to commit often, and commit short changes.  They are
local.  They won't break the remote tree for anyone else.

Merging can also be done much more often.  This means that it's
ok to merge or rebase a pile of local changes 10 or 20 times,
while they are being developed.  If the first sort of merging
described above is chosen, then repeated merges work
incrementally, so conflicts that have been resolved in one of the
past merges don't reappear in future merges.

> With git, I would guess that the same situation obtains until
> you do `git push' with your changes.  Thus, I think that `git
> push' is the true analogue to CVS commit.

If a dSCM repository is `anointed' by the team as *the*
repository, then there are hooks which can control whether:

    * It is ok to create `remote heads' with unmerged changes
      (this is what happens for example if someone pushes the
      sample history graph shown above, before the merge of
      change [9] happens)

    * It is ok to push new `branches' in the remote tree

> This is based on surmise rather than knowledge.  If it is
> wrong, where is the mistake?

It's mostly right.  A `push' operation is that `publishes' a
change in a dSCM world.  The only difference is that a `commit'
in a centralized SCM (like CVS) does several things, which have
been split in a more fine-grained set of operations in a
distributed SCM system.  When a commit happens in CVS then:

    * A local `merge' has completed

    * CVS add, or remove commands have been completed

    * A commit sends the files to the remote server (the
      `publishing' part)

    * The local workspace state is updated to match the new state
      of the tree

In a distributed SCM a `commit' is only part of the above:

    * A changeset is recorded in the local repository storage
      area

    * Local workspace state is updated

A merge is not strictly necessary, and the changes haven't been
published anywhere else yet.

HTH,
Giorgos





reply via email to

[Prev in Thread] Current Thread [Next in Thread]