Distributed LedgerSMB Development With DVCS - Git

This content is outdated and kept here for reference only!

See Getting Started (Developing) for up to date information

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://svn.code.sf.net/p/ledger-smb/code/ 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
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 ..." 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 ..." 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 [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.

Operating system