Subject: Re: simple cvs-like git wrapper

From: Jakub Narebski <[email-masked]>
Date: Fri, 1 Feb 2008 16:35:36 +0100

On Wed, 30 Jan 2008, Ed S. Peschko wrote:
> Jakub narebski wrote:   <-- re added

Please try to not remove attributions. TIA.

>> One thing (besides horrible branching and even worse merging)  which I
>> hated in multi-user CVS is the "cvs update", namely the fact that if
>> you want to commit changes, you _have_ to rebase them on top of
>> current work. So when you are ready to commit, when you have tested
>> everything, you are sometimes forced to resolve a merge to be able to
>> commit... and have to test resolved merge... and perhaps again, and
>> again.
> 
> Yeah, I realize that it's not exactly the best solution for every
> project, but for projects tied to a piece of hardware (ie: a database, a
> particular box, etc), its much more important to be in sync, to have 
> 'one true view' of the world rather than to have the freedom to have 
> multiple views.
> 
> In our case, our code is tied to a database and a database instance. An
> environment equals attachment to a given oracle SID. If someone is out of sync
> with other people's changes, then that person's environment is wrong.

Err, if it is as bad as you say, and it is not possible to change
environment to what is saved in commit [message] on git-checkout
and on git-reset this just removes any possibility of parallel
development. Not that CVS-like centralized development would do
much better in such case...

It would be nice to save environment state somehow in the commit,
or in worktree / commit tree. Versioning databases (or is it just
database schema) is PITA, and I don't know any good solution. phpBB
modules which need to modify database have some kind of diff-like
thing, but...

[cut]
----
Below there is description of "cvs update" workflow and how it can
be implemented in git, rebase based workflow which is very similar
but allows to generate small incremental commits while retaining
linear history, and default merge based workflow.

(Perhaps something like that should be added to cvs-migration.txt?)

Let's assume that time, or rather parentage/sequence of commits flow
from left to right, so "A---B" means that B is child of commit A (is
later revision), and that A is parent of commit B.  Let us mark
uncommited changes by '*'.

1. First, how 'cvs commit' and 'cvs update' works.
1.1. The case where there were no changes in the central (origin)
     repository

     before "cvs commit"

       A---B---C---* 

     after "cvs commit"

       A---B---C---D

1.2. The case where there were changes in the origin repo
     ("cvs commit" says: need to update, or something like that)

     before "cvs commit", and "cvs update"

       A---B---C---*

     after "cvs update"

       A---B---C---d---e---*'

     where *' means that the state might be modified wrt. *; you might
     have to resolve conflicts, while still not having you work saved
     under version control anywhere

     after "cvs commit" (and after resolving conficts, if there were any)

       A---B---C---d---e---F 

You can implement such workflow in git by stashing your changes, doing
fasfforward-only pull (or fetch), then unstashing changes, resolving
conflicts if there are any, and finally commiting changes. You would
have to implement "needs update" pre-commit hook if you want to follow
CVS workflow fully.

NOTE that while you are working on '*' somobody might have changed
environment!

2. Rebase based workflow; the "git pull --rebase" needs new enough git
   version

   before your work (common base both on your local repository, and
   in the origin / central / distribution point one)

     A---B---C

   you create a few commits, splitting your work into small, self
   contained, easy to understand, bisectable commits

     A---B---C---1---2

   now you want to be up to date wrt central repository, to send your
   changes (push, publish) to central repo, via "git pull --rebase"

     A---B---C---1---2
              \
               \-d---e

     A---B---C---1---2
              \
               \-d---e---1'---2'

     A---B---C---d---e---1'---2'

   where 1' and 2' are your commits modified by the presence of
   'd' and 'e' in the commit chain. Note that in the process of moving
   (copying) your changes on top of fetched changes from central repo
   there can be conflicts.

3. Merge based workflow; ordinary "git pull"

   before your work (common base both on your local repository, and
   in the origin / central / distribution point one)

     A---B---C

   you create a few commits, splitting your work into small, self
   contained, easy to understand, bisectable commits

     A---B---C---1---2

   now you want to be up to date wrt central repository, to send your
   changes (push, publish) to central repo, via "git pull"

     A---B---C---1---2
              \
               \-d---e

     A---B---C---1---2---M
              \         /
               \-d---e-/

   where M is a merge commit; you might have to resolve conflicts here.

-- 
Jakub Narebski
Poland