1. Summary
  2. Files
  3. Support
  4. Report Spam
  5. Create account
  6. Log in

Git intro

From fpdb

Jump to: navigation, search

Contents

Git Instructions

Hi, welcome to the git guide for fpdb devs!

FPDB has chosen to use git as the tool to manage the source code for the project. Git is very flexible and suited to the needs of the project - but it doesn't work in the traditional manner.

I've (Sorrow/Carl) decided to rewrite this guide as I set up my own machine for git usage. I'll configure the local repository, configure several shortcuts, create a patch, then update my tree from other developers, update my tree with some experimental code, and revert the update.

Getting it

Windows go to http://code.google.com/p/msysgit/downloads/list and install it.

Ubuntu / debian: sudo apt-get install git-core

Gentoo: emerge git -av

Cloning Sorrow's tree

Chaz's is the "main" FPDB tree, most releases come from master of that tree. That makes it a good place to start your own modifications from.

Choose/create a directory you are going to work in. I'm using ~/fpdb-git

mkdir ~/fpdb-git
cd ~/fpdb-git
git clone git://github.com/ChazDazzle/fpdb-chaz.git

You should see something like:

~/fpdb-git $  git clone git@git.assembla.com:fpdboz.git
Initialized empty Git repository in /home/carlos/fpdb-git/fpdb/.git/
remote: Counting objects: 9991, done.
remote: Compressing objects: 100% (6827/6827), done.
remote: Total 9991 (delta 7443), reused 4289 (delta 3151)
Receiving objects: 100% (9991/9991), 6.23 MiB | 483 KiB/s, done.
Resolving deltas: 100% (7443/7443), done.

Some prep work.

We work in a decentralised fashion, with each developer having his own public git repository, and usually one or two local repositories. After the last step you now have a local source tree of your very own, based on the main fpdb tree.

Full git pathnames can get a bit unwieldy at times, and you are likely going to want to track more than one developers repository.

The following is a list of repositories and aliases that I use:

git remote add chaz git://github.com/ChazDazzle/fpdb-chaz.git
git remote add carl git://git.assembla.com/fpdboz.git
git remote add dooglus git://repo.or.cz/fpdb-dooglus.git
git remote add eric git://git.assembla.com/fpdb-eric.git
git remote add ferki git://ferki.hopto.org/fpdb
git remote add gimick git://git.assembla.com/fpdb-gimick.git
git remote add kangaderoo git://github.com/kangaderoo/fpdb-kangaderoo.git
git remote add moomoo git://git.moomoocamp.net/fpdb-moo.git
git remote add steffen git://git.assembla.com/fpdb.git
git remote add wielinga git://github.com/rwielinga/fpdb.git

git remote add ray git://git.assembla.com/free_poker_tools.git
git remote add mct git://git.assembla.com/mctfpdb.git
git remote add mika git://repo.or.cz/fpbd-bostik.git
git remote add sqlcoder git://git.assembla.com/fpdb-sql.git
git remote add grindi git://github.com/grindi/fpdb-grindi.git
git remote add peas git://git.assembla.com/fpt_fpdb.git
git remote add juergen git://git.assembla.com/fpdb-mme.git

If you want to create tracking branches for the various trees do this (will be completed):

git fetch carl
git branch --track carl carl/master
git fetch chaz
git branch --track chaz chaz/chazdazzle
git fetch dooglus
git branch --track dooglus dooglus/master
git fetch eric
git branch --track eric eric/master
git fetch ferki
git branch --track ferki ferki/master
git fetch gimick
git branch --track gimick gimick/master
git fetch kangaderoo
git branch --track kangaderoo kangaderoo/master
git fetch moomoo
git branch --track moomoo moomoo/master
git fetch steffen
git branch --track steffen steffen/master
git fetch wielinga
git branch --track wielinga wielinga/master

If you are working from the console, set the environment variable $EDITOR to your editor of choice - I use vim.

I also use this tidbit in my bash environment:

# Combining Lachie Cox's crazy Git branch mojo:
#   http://spiral.smartbomb.com.au/post/31418465
# with 
#   http://henrik.nyh.se/2008/12/git-dirty-prompt
# AND Geoff Grosenbach's style:
#   http://pastie.org/325104
# Sweeeeeeeet!

function parse_git_dirty {
  [[ $(git status 2> /dev/null | tail -n1) != "nothing to commit (working directory clean)" ]] && echo "(☠)"
}
function parse_git_branch {
  git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e "s/* \(.*\)/\1$(parse_git_dirty)/"
}
export PS1='\[\033[01;32m\]\w $(git branch &>/dev/null; if [ $? -eq 0 ]; 
then echo "\[\033[01;34m\]$(parse_git_branch)"; fi) \$ \[\033[00m\]'

Which colourises my console display, and tells me 1. Which branch in in 2. If the contents of the repo have been changed compared to the branch. I have no idea if this will work on windows.

Making a (local) commit

Ok - I have a patch that needs to go in to fix a sqlite problem in the new Session Viewer. SQLite doesn't have some of the standard SELECT aggregate functions, and the new viewer took advantage of it.

I've made the required changes to fpdb_db.py by just editing the file directly in the local repository.

To view the changes i've made:

git diff

Which gives me:

diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py
index 1895888..27291d7 100644
--- a/pyfpdb/fpdb_db.py
+++ b/pyfpdb/fpdb_db.py
@@ -30,11 +30,29 @@ except ImportError:
     logging.info("Not using sqlalchemy connection pool.")
     use_pool = False
 
+try:
+    from numpy import var
+    use_numpy = True
+except ImportError:
+    logging.info("Not using numpy to define variance in sqlite.")
+    use_numpy = False
 
 import fpdb_simple
 import FpdbSQLQueries
 import Configuration
 
+# Variance created as sqlite has a bunch of undefined aggregate functions.
+
+class VARIANCE:
+    def __init__(self):
+        self.store = []
+
+    def step(self, value):
+        self.store.append(value)
+
+    def finalize(self):
+        return float(var(self.store))
+
 class fpdb_db:
     MYSQL_INNODB = 2
     PGSQL = 3
@@ -130,6 +148,10 @@ class fpdb_db:
                                      , detect_types=sqlite3.PARSE_DECLTYPES )
             sqlite3.register_converter("bool", lambda x: bool(int(x)))
             sqlite3.register_adapter(bool, lambda x: "1" if x else "0")
+            if use_numpy:
+                self.db.create_aggregate("variance", 1, VARIANCE)
+            else:
+                logging.warning("Some database functions will not work without NumPy support")
         else:
             raise FpdbError("unrecognised database backend:"+backend)
         self.cursor = self.db.cursor()

git diff showed me the difference between the last code commit, and my local changes.

I've tested the change, I now want to commit the change to my local repo.

git commit fpdb_db.py

This will pop you into an editor (as defined by $EDITOR) looking like:


# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Explicit paths specified without -i nor -o; assuming --only paths...
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   fpdb_db.py

Add your eloquent change description and exit your editor.

(NOTE: You can add multiple files to the command line, or use '-a' instead of the file name to include all modified files. The '-a' option only adds tracked files to the changeset, not additional temporary files you may have created)

To make sure the change has been committed there are a couple of things you can do.

First make sure you didn't forget to add a file to your last commit and run

git diff

If you have any remaining changes git diff will show you.

Now run

git log

And you should see somehting like

commit c9b9c848be49f4feb44611c0ab7b53d9b3a1575d
Author: Worros <carl.gherardi@gmail.com>
Date:   Mon Nov 16 15:19:24 2009 +0800

    Add aggregate function VARIANCE() for sqlite

Along with every other changeset that has gone before.

Pulling updates from other trees

(see the next section if you want to inspect the changesets before really pulling)

Great - I have a changeset that should be published, but before I do that I should make sure my tree is up to date with the main tree as it has probably moved on from the last time we 'pulled' in his changes.

git pull ray master

If you'd set up the remotes/aliases from earlier that should have looked something like:

~/Projects/fpdb/fpdboz/pyfpdb master $ git pull ray master
From git://git.assembla.com/free_poker_tools
 * branch            master     -> FETCH_HEAD
Merge made by recursive.
 pyfpdb/Configuration.py        |  145 ++++++++++++++++++++--------------------
 pyfpdb/Database.py             |   21 +-----
 pyfpdb/Exceptions.py           |    4 +-
 pyfpdb/HUD_main.py             |   21 ++++--
 pyfpdb/HandHistoryConverter.py |   36 ++++++++---
 pyfpdb/Hud.py                  |    8 +-
 pyfpdb/PokerStarsToFpdb.py     |   30 +++++----
 pyfpdb/SQL.py                  |   13 ++--
 pyfpdb/TableWindow.py          |   26 +++----
 pyfpdb/XTables.py              |    3 +-
 pyfpdb/fpdb_import.py          |   10 +---
 pyfpdb/py2exe_setup.py         |   25 ++++++-
 12 files changed, 184 insertions(+), 158 deletions(-)
 mode change 100644 => 100755 pyfpdb/Tables_Demo.py

(NOTE: Strictly the fetch step isn't necessary so I skipped over it.)

Looks like there were a few changes - good for me there were no conflicting changes, and i'm good to go.

Run 'git log' to see the changes that were pulled into your repo.

Pulling updates from other trees but inspecting them first

As an example I'll show how to set this up for steffen's tree. This guide assumes that you set up the aliases as described in the earlier prep work section. In Windows this guide will only work if you have Cygwin or sth. similar.

The first time for each remote tree/branch you have to create a new local branch like this:

git checkout -b steffen steffen/master

Future times you simply change to the branch like this:

git checkout steffen

Now pull the remote branch and checkout your own master branch again:

git pull
git checkout master

This command shows changesets that are in my tree but not in yours:

gitk steffen --not $( git show-ref --heads | cut -d' ' -f2 | grep -v '^refs/heads/steffen' ) &

Once you are happy with what you pulled merge your local branch containing my tree into your master tree:

git merge steffen

Pushing to your own tree

FIXME - incomplete - different depending on site. Basically you set your origin and git push

Branches and experimental code

You have been working on the master branch of your repository, you may want to try some experimental changes from another developer without polluting your own pristine master branch.

Grindi as been working on some SQLAlchemy code I want to take a look at.

I'm going to create a temporary branch:

~/Projects/fpdb/fpdboz/pyfpdb master $ git branch newimport
~/Projects/fpdb/fpdboz/pyfpdb master $ git checkout newimport
Switched to a new branch 'newimport'
~/Projects/fpdb/fpdboz/pyfpdb newimport $ 

And pull Grindis 'newimport' branch onto my own

~/Projects/fpdb/fpdboz/pyfpdb newimport $ git pull grindi newimport
From git://github.com/grindi/fpdb-grindi
 * branch            newimport  -> FETCH_HEAD
Auto-merging pyfpdb/Database.py
Auto-merging pyfpdb/DerivedStats.py
CONFLICT (content): Merge conflict in pyfpdb/DerivedStats.py
Auto-merging pyfpdb/fpdb_db.py
Auto-merging pyfpdb/fpdb_import.py
Automatic merge failed; fix conflicts and then commit the result.

Ouch! - merge conflict. Fortunately its only in the onw file.

Resolving merge conflicts is beyond the scope of what i'm trying to document here - git mergetool is your friend through.

I want to get back to working on my master branch

~/Projects/fpdb/fpdboz/pyfpdb newimport(☠) $ git co master
pyfpdb/DerivedStats.py: needs merge
error: you need to resolve your current index first

My repository is in a 'hung state' until I resolve the failed merge.

Rather than resolve the merge, i'm just going to revert the change

~/Projects/fpdb/fpdboz/pyfpdb newimport(☠) $ git reset --hard
HEAD is now at 5b02153 Merge branch 'master' of git://git.assembla.com/free_poker_tools
~/Projects/fpdb/fpdboz/pyfpdb newimport $ git co master
Switched to branch 'master'

Much better.

Keeping a clean master branch (Interactive Rebase)

A lot of time working on a bug or feature causes you to put in several bad or just useless commits. Even if this is done in its separate branch, merging the final result into master ends up in all of the intermediate commits coming in with the merge. The cluttering of commit logs is a minor issue, but having to display the several wrong steps that it took is usually a little embarrassing. The solution to this is an interactive rebase.

Say you want to fix a small graphing oddity. Start off by branching off from master:

(in master branch)
git checkout -b graphfix

Then hack around and finally, after 15-20 iterations of trial and error you have the fix ready, and it amounts to maybe 10 changed lines in all. You would like to have the fix in a single commit. One approach would be to get a git-diff from the branching point, save it as a patch and then git-apply it in the master. But that's cumbersome. Let's use the interactive rebase, in the safest way possible:

Copy the fix branch:

git checkout -b graphmerge

This way the fix history remains intact in the original graphfix branch, and if you make an error in rebase, you can start from the known point again.

Rework the patch series:

git rebase -i master

This command does an in-tree interactive rebase, so it will modify the current branch you are in. The command finds the series of commits since the branching point in master and lists them in reverse chronological order in your chosen editor. The lines look like this:

State how commits are treated:

pick 0f38a2bb Latest commit
pick 82a7cc02 Previous commit
pick 345bba10 Previous to that
pick d74ba942 Yet another
pick f0a1b8b7 Even earlier one

Leave the top line as it is, and change the other lines to read squash instead of pick, like this:

pick 0f38a2bb Latest commit
squash 82a7cc02 Previous commit
squash 345bba10 Previous to that
squash d74ba942 Yet another
squash f0a1b8b7 Even earlier one

Save, and you will be prompted to edit the commit message you want for the single commit. All the commits that are specified to be squashed are then invisibly merged together in the picked commit. Effectively their net result is made into a single patch. The branch is rewritten and the squashed commits will now disappear entirely.

Finally merge the squashed branch to your master:

git checkout master
git merge graphmerge

The reason we used the separate branch for staging the rebase is that if you for make an error, you can toss the copied branch and start again from the head of the fix branch. Once the result branch looks good for merging into master, you can do that and delete the temporary feature-or-fix branches. All your embarrassing and/or needless steps have vanished from the published tree, and a single fix is available as a single commit.

Git Stash

One of the most common scenarios is to have a set of uncommitted changes to your local tree, but you want to change branches or pull some new code from someone else. The usual description of this is

1. Work on something useful, but its not ready to commit yet. 2. Boss comes along and tells you to fix the issue reported by customer.

The usual solution is to commit your changes as a temporary commit, then co the branch you need to fix, then return to your temp checkout.

git stash

Will put all uncommitted changes away into a 'stash' and revert your tree into the state of its last commit.

You are then able to change branches, or pull code, then 'git stash pop' your changes back after your done.

Git GUI Tools

A selection of GUI tools that may help you with using git. Please expand this section

git-cola

A handy tool to display your edits since the last commit and to comfortably pull/push/stash. If you open cola-classic from within it it display the git-handled directory structure and lets you see the history of any file.

gitg

Very nice GUI view of the timeline of changes. It also displays in an easily comprehensible way how merges happened, which changeset is based on which other one, etc.

egit

Git-plugin for Eclipse TODO

How to use tags for supporting users running releases/snapshots

Very simple. For example, to change to the exact that is in the 0.20 tarball run this:

git checkout 0.20

To change back to your normal master tree:

git checkout master

RSS/notification of updates

TODO

Howto git bisect

Git bisect helps you locate the exact commit that caused a certain behaviour. It is usually used to identify the commit that caused a bug. This looks long and difficult, but trust me, it's not. I've tried to be as detailed as I could, but since I already know this feature I may have missed something. If anything is unclear, please ask me (Steffen).

Preparation

(if you never edited any fpdb file you can skip this line.) You may not have any uncommitted changes in your tree. You can check with "git status" - if it shows any modified files, you will need to commit, stash, or remove your changes.

Once this is done you will need to go to the root of your fpdb directory. This is the directory that contains, amongst other files, the run_fpdb.py script.

Now run this to ensure that there are no leftovers from a previous bisect:

git bisect reset

Identifying a bad (ie. broken) commit

Since you are experiencing a bug this part is easy. Make sure that you have currently checked out the version that is showing the bug and type:

git bisect bad

Going back in history to find a good (ie. working) commit

The best way to do this is to go by releases. Let's have a look at an example:

git checkout 0.22

Now you've checked out version 0.22. Check if the bug persists. If the bug still happpens:

git bisect bad

Repeat this until you identify a good commit. The releases before 0.22, in reverse order (ie., in the order that you should try) are: 0.21, 0.21_rc2, 0.21-rc1, 0.20.906, 0.20.905, 0.20.904, 0.20.903, 0.20.902, 0.20.901, 0.20.1, 0.20

However, if the bug is gone, you have identified a good commit, then type:

git bisect good

Actually identifying the bad commit

Once you have told bisect about a good and a bad commit it will automatically checkout the best commit that you need to try to localise the problem. So simply try if your problem persists, and if it does you run "git bisect bad". If the problem is gone you run "git bisect good". If a particular commit is broken in some way that prevents you from testing for your bug you need to type "git bisect skip".

Once the bad commit has been identified git will tell you the commit id. Tell us this in IRC, the mailing list, or a bug, and it'll be much easier for us to fix the bug.

Personal tools