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

Distributed LedgerSMB Development With DVCS - Git



=================================================
Distributed LedgerSMB Development With DVCS - Git
=================================================
2008-08-11
By Jeff Kowalczyk (jfkw)

I've been working on my local LedgerSMB deployment customization
using the distributed version control system, git. I'm relatively
new to git, but it's really helping me in the following areas:

* Fixing bugs in branches/1.2

* Making necessary customizations that are unsuitable for
  upstream

* Layering multiple customization branches on each other to get
  the configuration required by a particular customer deployment

* Putting templates and graphics under version control

* Putting the plaintext backup of the company database under
  version control. At any time I can and do make snapshots, then
  examine the diff to see how each LedgerSMB operation affects
  the database tables.

LedgerSMB Development and DVCS
==============================

The LedgerSMB projet is organized around a team of core-devs,
with exclusive commit priviledges to the centralized subversion
repository hosted on Sourceforge.

There seem to be many very capable developers in the LedgerSMB
and SQL-Ledger communities. Their customization and bugfix work
is of a quality and timeliness that we all would like to see and
use it as early as possible. However, the core-devs must be
prudent about pulling untested and possibly incompatible changes
into the mainline repository.

To energize LedgerSMB development, I'm interested in working with
any interested parties to start collaborating the DVCS way. I
think having the non-committer contributors using a DVCS system
and following some sensible conventions will help the core-devs
make the best use of their time to pull from DVCS contributors.

Those of us who want to can used DVCS without requiring the
central repository to change to DVCS.

Even more importantly, it will bring the important and eagerly
anticipated work being done (such as the recent payment
functionality by mighty-d) out into the collaborative space. This
should help speed the collective work along, and improve its
quality along the way.

Cloning the LedgerSMB Sourceforge Subversion Repository
=======================================================

In time we may have an official git mirror from which to clone (a
very quick copy operation), but you can make your own clone of
the LedgerSMB repository directly from Sourceforge:

  $ git svn clone https://ledger-smb.svn.sourceforge.net/svnroot/ledger-smb/ ledgersmb
  Initialized empty Git repository in /path/to/ledgersmb/.git/
  	A	ledger-smb/login.pl
  	A	ledger-smb/menu.ini
  	A	ledger-smb/ledger-smb.gif
  	A	ledger-smb/is.pl
  	A	ledger-smb/VERSION
  (..., ..., go get coffee)

Fixing A Bug Using Git And Bugfix Branch
========================================

While working on my local branches/1.2, I came to conversation
about a proposed trunk feature. I switched to trunk, and tested
the current state of trunk. During that test, I found a simple
bug in the schema definition, filed as SF2046815:

  ERROR: column e.control_code does not exist LINE 1:
  ..._ap_account_id, ec.cash_account_id, ec.threshold,
  e.control_... ^ QUERY: SELECT c.id, e.id, ec.entity_class,
  ec.discount, ec.taxincluded, ec.creditlimit, ec.terms,
  ec.meta_number, ec.business_id, ec.language_code,
  ec.pricegroup_id, ec.curr, ec.startdate, ec.enddate,
  ec.ar_ap_account_id, ec.cash_account_id, ec.threshold,
  e.control_code, ec.id FROM company c JOIN entity e
  ON (c.entity_id = e.id) JOIN entity_credit_account ec
  ON (c.entity_id = ec.entity_id) WHERE e.id = $1 AND
  ec.entity_class = CASE WHEN $2 = 3 THEN 2 WHEN $2 IS NULL THEN
  ec.entity_class ELSE $2 END CONTEXT: PL/pgSQL
  function "entity__list_credit" line 4 at FOR over SELECT rows

This is a one-liner fix, but it is still worth it to make a
branch, since fast branching and easy merging are strengths of
git. The practice scales up well when you want to maintain
multiple branches and share them with others.

I intend my branch to be against the current trunk, so I check
that branch out. I have my prompt set up to display the current
branch in parentheses.

  (1.2_jfkw) $ git checkout trunk
  Note: moving to "trunk" which isn't a local branch
  If you want to create a new branch from this checkout, you may do so
  (now or later) by using -b with the checkout command again. Example:
    git checkout -b <new_branch_name>
  HEAD is now at cb92467... Adding meta_number to company_billing_info return set

I am in the habit of updating the branch to the latest revision
before branching:

  (cb92467...) $ git svn rebase --all
  Current branch HEAD is up to date.

Now, we'll make a bugfix-branch, I prefer it to be named after
the SF bug:

  (cb92467...) $ git checkout -b 1.3_SF2046815_missing_entity_control_code
  Switched to a new branch "1.3_SF2046815_missing_entity_control_code"

You can use the git branch command to list all local
branches. For example, I'm keeping around all branches for bugs
and features I've worked on:

  $ git branch
    1.2_SF1877860_typo
    1.2_SF1928336_renames
    1.2_SF2013331_cookie_name
    1.2_SF2025931_till_equals_1
    1.2_cdog
    1.2_cdog_templates
    1.2_generate_salesorders_detail_default
    1.2_jfkw
    1.2_partnumber_like_space_delimiter
    1.2_print_pdf_default
    1.2_project_generate_orders
    1.2_receipts_on_invoice_screen
    1.2_require_customernumber
    1.2_require_customernumber_set_to_name
    1.2_sql_ins_customer_ins_project
    1.3_SF2013331_cookie_name
    1.3_SF2017284_smallgray_css
    1.3_SF2043569_install_doc
  * 1.3_SF2046815_missing_entity_control_code
    1.3_jfkw
    master

Note that the remote branches (trunk, 1.2) are seen with the git
branch -a command. You should never modify those, just think of
them as read-only. Git will keep track of the remote origin
branch your local branch came from.

Back to the bugfixing task at hand. Edit the offending file:

  (1.3_SF2046815_missing_entity_control_code) $ emacsclient -n sql/Pg-database.sql

And in your editor, fix, save, test, etc. When ready, view a diff
of the branch tip (HEAD) to your working copy:

  (1.3_SF2046815_missing_entity_control_code) $ git diff
  diff --git a/sql/Pg-database.sql b/sql/Pg-database.sql
  index e1d8251..5bf84c3 100644
  --- a/sql/Pg-database.sql
  +++ b/sql/Pg-database.sql
  @@ -19,6 +19,7 @@ CREATE index entity_class_idx ON entity_class(lower(class));

   CREATE TABLE entity (
     id serial UNIQUE,
  +  control_code text not null,
     name text check (name ~ '[[:alnum:]_]'),
     entity_class integer references entity_class(id) not null ,
     created date not null default current_date,

At this point you encounter something unique about git. You have
an intermediary layer between your working copy and HEAD, called
the index. The index has been described variously as 'the next
commit'.

Use the git status command to see what has changed in your
working copy:

  (1.3_SF2046815_missing_entity_control_code) $ git status
  # On branch 1.3_SF2046815_missing_entity_control_code
  # Changed but not updated:
  #   (use "git add <file>..." to update what will be committed)
  #
  #       modified:   sql/Pg-database.sql
  #
  no changes added to commit (use "git add" and/or "git commit -a")

And decide which files among these, in whole or just in part
should be added to the index, which is to be the next commit.

In this case, there's only one file changed, so you can add it to
the next local commit by filename, or by adding all under the current
directory (e.g. '.'):

  (1.3_SF2046815_missing_entity_control_code) $ git add .

Check the status now, where you see that file added to the index
is designated 'to be committed'.

  (1.3_SF2046815_missing_entity_control_code) $ git status
  # On branch 1.3_SF2046815_missing_entity_control_code
  # Changes to be committed:
  #   (use "git reset HEAD <file>..." to unstage)
  #
  #       modified:   sql/Pg-database.sql
  #

Commiting Your Changes
======================

Looks good, we're ready to commit:

  (1.3_SF2046815_missing_entity_control_code) $ git commit -m 'add missing entity.control_code column'
  Created commit a3503cb: add missing entity.control_code column
   1 files changed, 1 insertions(+), 0 deletions(-)

If you have commit rights to the repository, you can git svn
dcommit your changes directly:

  (1.3_SF2046815_missing_entity_control_code) $ git svn dcommit --help
  git-svn - bidirectional operations between a single Subversion tree and git
  Usage: /usr/bin/git-svn <command> [options] [arguments]
    dcommit          Commit several diffs to merge with upstream
  (...)

Or, Generate A Patch
====================

If you don't have commit rights, and you're simply patching a bug
from the tracker, make a diff of your mature/completed bug branch
to its origin branch appropriate documentation:

  (1.3_SF2046815_missing_entity_control_code) $ git diff trunk > 1.3_SF2046815_missing_entity_control_code.diff

And upload 1.3_SF2046815_missing_entity_control_code.diff as a
patch with appropriate documentation.

DVCS Documentation Forthcoming
==============================

Next opportunity, I'll document the above using a git hosting
service such as gitorious or github. With a shared git repository
you can share your branches with others who may want to
collaborate or test. Best of all you can ask the LedgerSMB
committers to pull from your repository when your branch is
mature enough to be accepted upstream.

If you're interested in using DVCS to contributed to LedgerSMB,
I'll be available on #ledgersmb as jfkw or on the mailing list
ledgersmb-dev.