diff --git a/pygit2.c b/pygit2.c
index ef74160..ad79352 100644
--- a/pygit2.c
+++ b/pygit2.c
@@ -49,6 +49,7 @@ OBJECT_STRUCT(Object, git_object, obj)
 OBJECT_STRUCT(Commit, git_commit, commit)
 OBJECT_STRUCT(Tree, git_tree, tree)
 OBJECT_STRUCT(Blob, git_blob, blob)
+OBJECT_STRUCT(Walker, git_revwalk, walk)
 
 typedef struct {
     PyObject_HEAD
@@ -77,9 +78,8 @@ typedef struct {
 
 typedef struct {
     PyObject_HEAD
-    Repository *repo;
-    git_revwalk *walk;
-} Walker;
+    git_reference *reference;
+} Reference;
 
 static PyTypeObject RepositoryType;
 static PyTypeObject ObjectType;
@@ -91,6 +91,7 @@ static PyTypeObject TagType;
 static PyTypeObject IndexType;
 static PyTypeObject IndexEntryType;
 static PyTypeObject WalkerType;
+static PyTypeObject ReferenceType;
 
 static PyObject *GitError;
 
@@ -163,6 +164,46 @@ Error_set_py_obj(int err, PyObject *py_obj) {
     return NULL;
 }
 
+static Object *
+wrap_object(git_object *obj, Repository *repo) {
+    Object *py_obj = NULL;
+    switch (git_object_type(obj)) {
+        case GIT_OBJ_COMMIT:
+            py_obj = (Object*)CommitType.tp_alloc(&CommitType, 0);
+            break;
+        case GIT_OBJ_TREE:
+            py_obj = (Object*)TreeType.tp_alloc(&TreeType, 0);
+            break;
+        case GIT_OBJ_BLOB:
+            py_obj = (Object*)BlobType.tp_alloc(&BlobType, 0);
+            break;
+        case GIT_OBJ_TAG:
+            py_obj = (Object*)TagType.tp_alloc(&TagType, 0);
+            break;
+        default:
+            assert(0);
+    }
+    if (!py_obj)
+        return (Object*)PyErr_NoMemory();
+
+    py_obj->obj = obj;
+    py_obj->repo = repo;
+    Py_INCREF(repo);
+    return py_obj;
+}
+
+static PyObject *
+wrap_reference(git_reference * c_reference)
+{
+    Reference *py_reference=NULL;
+
+    py_reference = (Reference *)ReferenceType.tp_alloc(&ReferenceType, 0);
+    if (py_reference == NULL)
+        return NULL;
+    py_reference->reference = c_reference;
+    return (PyObject *)py_reference;
+}
+
 static int
 py_str_to_git_oid(PyObject *py_str, git_oid *oid) {
     char *hex;
@@ -224,34 +265,6 @@ Repository_contains(Repository *self, PyObject *value) {
     return git_odb_exists(git_repository_database(self->repo), &oid);
 }
 
-static Object *
-wrap_object(git_object *obj, Repository *repo) {
-    Object *py_obj = NULL;
-    switch (git_object_type(obj)) {
-        case GIT_OBJ_COMMIT:
-            py_obj = (Object*)CommitType.tp_alloc(&CommitType, 0);
-            break;
-        case GIT_OBJ_TREE:
-            py_obj = (Object*)TreeType.tp_alloc(&TreeType, 0);
-            break;
-        case GIT_OBJ_BLOB:
-            py_obj = (Object*)BlobType.tp_alloc(&BlobType, 0);
-            break;
-        case GIT_OBJ_TAG:
-            py_obj = (Object*)TagType.tp_alloc(&TagType, 0);
-            break;
-        default:
-            assert(0);
-    }
-    if (!py_obj)
-        return (Object*)PyErr_NoMemory();
-
-    py_obj->obj = obj;
-    py_obj->repo = repo;
-    Py_INCREF(repo);
-    return py_obj;
-}
-
 static PyObject *
 Repository_getitem(Repository *self, PyObject *value) {
     git_oid oid;
@@ -273,7 +286,8 @@ Repository_getitem(Repository *self, PyObject *value) {
 }
 
 static int
-Repository_read_raw(git_odb_object **obj, git_repository *repo, const git_oid *oid) {
+Repository_read_raw(git_odb_object **obj, git_repository *repo,
+                    const git_oid *oid) {
     return git_odb_read(obj, git_repository_database(repo), oid);
 }
 
@@ -485,6 +499,87 @@ Repository_create_tag(Repository *self, PyObject *args) {
     return PyString_FromStringAndSize(hex, GIT_OID_HEXSZ);
 }
 
+static PyObject *
+Repository_listall_references(Repository *self, PyObject *args)
+{
+    git_strarray c_result;
+    PyObject *py_result, *py_string;
+    unsigned index;
+    int err;
+
+    /* 1- Get the C result */
+    /* TODO We can choose an other option (instead of GIT_REF_LISTALL) */
+    err = git_reference_listall (&c_result, self->repo, GIT_REF_LISTALL);
+    if (err < 0)
+        return Error_set(err);
+
+    /* 2- Create a new PyTuple */
+    if ( (py_result = PyTuple_New(c_result.count)) == NULL) {
+        git_strarray_free(&c_result);
+        return NULL;
+    }
+
+    /* 3- Fill it */
+    for (index=0; index < c_result.count; index++) {
+        if ((py_string = PyString_FromString( (c_result.strings)[index] ))
+             == NULL) {
+            Py_XDECREF(py_result);
+            git_strarray_free(&c_result);
+            return NULL;
+        }
+        PyTuple_SET_ITEM(py_result, index, py_string);
+    }
+
+    /* 4- Destroy the c_result */
+    git_strarray_free(&c_result);
+
+    /* 5- And return the py_result */
+    return py_result;
+}
+
+static PyObject *
+Repository_lookup_reference(Repository *self, PyObject *py_name)
+{
+    git_reference *c_reference;
+    char *c_name;
+    int err;
+
+    /* 1- Get the C name */
+    c_name = PyString_AsString(py_name);
+    if (c_name == NULL)
+        return NULL;
+
+    /* 2- Lookup */
+    err = git_reference_lookup(&c_reference, self->repo, c_name);
+    if (err < 0)
+      return Error_set(err);
+
+    /* 3- Make an instance of Reference and return it */
+    return wrap_reference(c_reference);
+}
+
+static PyObject *
+Repository_create_reference(Repository *self,  PyObject *args)
+{
+    git_reference *c_reference;
+    char *c_name;
+    git_oid oid;
+    int err;
+
+    /* 1- Get the C variables */
+    if (!PyArg_ParseTuple(args, "sO&", &c_name,
+                                       py_str_to_git_oid, &oid))
+        return NULL;
+
+    /* 2- Create the reference */
+    err = git_reference_create_oid(&c_reference, self->repo, c_name, &oid);
+    if (err < 0)
+      return Error_set(err);
+
+    /* 3- Make an instance of Reference and return it */
+    return wrap_reference(c_reference);
+}
+
 static PyMethodDef Repository_methods[] = {
     {"create_commit", (PyCFunction)Repository_create_commit, METH_VARARGS,
      "Create a new commit object, return its SHA."},
@@ -494,6 +589,15 @@ static PyMethodDef Repository_methods[] = {
      "Generator that traverses the history starting from the given commit."},
     {"read", (PyCFunction)Repository_read, METH_O,
      "Read raw object data from the repository."},
+    {"listall_references", (PyCFunction)Repository_listall_references,
+      METH_NOARGS,
+      "Return a list with all the references that can be found in a "
+      "repository."},
+    {"lookup_reference", (PyCFunction)Repository_lookup_reference, METH_O,
+       "Lookup a reference by its name in a repository."},
+    {"create_reference", (PyCFunction)Repository_create_reference, METH_VARARGS,
+     "Create a new reference \"name\" that points to the object given by its "
+     "\"sha\"."},
     {NULL}
 };
 
@@ -530,7 +634,7 @@ static PyTypeObject RepositoryType = {
     0,                                         /* tp_getattr */
     0,                                         /* tp_setattr */
     0,                                         /* tp_compare */
-    0,                                         /* tp_repr */
+    0,                                        /* tp_repr */
     0,                                         /* tp_as_number */
     &Repository_as_sequence,                   /* tp_as_sequence */
     &Repository_as_mapping,                    /* tp_as_mapping */
@@ -1712,6 +1816,131 @@ static PyTypeObject WalkerType = {
     0,                                         /* tp_new */
 };
 
+static PyObject *
+Reference_resolve(Reference *self, PyObject *args)
+{
+    git_reference *c_reference;
+    int err;
+
+    /* 1- Resolve */
+    err = git_reference_resolve(&c_reference, self->reference);
+    if (err < 0)
+      return Error_set(err);
+
+    /* 2- Make an instance of Reference and return it */
+    return wrap_reference(c_reference);
+}
+
+static PyObject *
+Reference_get_target(Reference *self, PyObject *args)
+{
+    const char * c_name;
+
+    /* 1- Get the target */
+    c_name = git_reference_target(self->reference);
+    if (c_name == NULL) {
+        PyErr_Format(PyExc_ValueError, "Not target available");
+        return NULL;
+    }
+
+    /* 2- Make a PyString and return it */
+    return PyString_FromString(c_name);
+}
+
+static PyObject *
+Reference_get_name(Reference *self) {
+    const char *c_name;
+
+    c_name = git_reference_name(self->reference);
+    return PyString_FromString(c_name);
+}
+
+static PyObject *
+Reference_get_sha(Reference *self) {
+    char hex[GIT_OID_HEXSZ];
+    const git_oid *oid;
+
+    /* 1- Get the oid (only for "direct" references) */
+    oid = git_reference_oid(self->reference);
+    if (oid == NULL)
+    {
+        PyErr_Format(PyExc_ValueError,
+        "sha is only available if the reference is direct (i.e. not symbolic)");
+        return NULL;
+    }
+
+    /* 2- Convert and return it */
+    git_oid_fmt(hex, oid);
+    return PyString_FromStringAndSize(hex, GIT_OID_HEXSZ);
+}
+
+static PyObject *
+Reference_get_type(Reference *self) {
+    git_rtype c_type;
+
+    c_type = git_reference_type(self->reference);
+    return PyInt_FromLong(c_type);
+}
+
+static PyMethodDef Reference_methods[] = {
+    {"resolve", (PyCFunction)Reference_resolve, METH_NOARGS,
+      "Resolve a symbolic reference and return a direct reference"},
+    {"get_target", (PyCFunction)Reference_get_target, METH_NOARGS,
+      "Get full name to the reference pointed by this symbolic reference."},
+    {NULL}
+};
+
+static PyGetSetDef Reference_getseters[] = {
+    {"name", (getter)Reference_get_name, NULL,
+     "The full name of a reference.", NULL},
+    {"sha", (getter)Reference_get_sha, NULL, "hex SHA",  NULL},
+    {"type", (getter)Reference_get_type, NULL,
+     "type (GIT_REF_OID, GIT_REF_SYMBOLIC or GIT_REF_PACKED).", NULL},
+    {NULL}
+};
+
+static PyTypeObject ReferenceType = {
+    PyObject_HEAD_INIT(NULL)
+    0,                                         /* ob_size */
+    "pygit2.Reference",                        /* tp_name */
+    sizeof(Reference),                         /* tp_basicsize */
+    0,                                         /* tp_itemsize */
+    0,                                         /* tp_dealloc */
+    0,                                         /* tp_print */
+    0,                                         /* tp_getattr */
+    0,                                         /* tp_setattr */
+    0,                                         /* tp_compare */
+    0,                                         /* tp_repr */
+    0,                                         /* tp_as_number */
+    0,                                         /* tp_as_sequence */
+    0,                                         /* tp_as_mapping */
+    0,                                         /* tp_hash */
+    0,                                         /* tp_call */
+    0,                                         /* tp_str */
+    0,                                         /* tp_getattro */
+    0,                                         /* tp_setattro */
+    0,                                         /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT,                        /* tp_flags */
+    "Reference",                               /* tp_doc */
+    0,                                         /* tp_traverse */
+    0,                                         /* tp_clear */
+    0,                                         /* tp_richcompare */
+    0,                                         /* tp_weaklistoffset */
+    0,                                         /* tp_iter */
+    0,                                         /* tp_iternext */
+    Reference_methods,                         /* tp_methods */
+    0,                                         /* tp_members */
+    Reference_getseters,                       /* tp_getset */
+    0,                                         /* tp_base */
+    0,                                         /* tp_dict */
+    0,                                         /* tp_descr_get */
+    0,                                         /* tp_descr_set */
+    0,                                         /* tp_dictoffset */
+    0,                                         /* tp_init */
+    0,                                         /* tp_alloc */
+    0,                                         /* tp_new */
+};
+
 static PyObject *
 init_repository(PyObject *self, PyObject *args) {
     git_repository *repo;
@@ -1786,6 +2015,9 @@ initpygit2(void)
     WalkerType.tp_new = PyType_GenericNew;
     if (PyType_Ready(&WalkerType) < 0)
         return;
+    ReferenceType.tp_new = PyType_GenericNew;
+    if (PyType_Ready(&ReferenceType) < 0)
+        return;
 
     m = Py_InitModule3("pygit2", module_methods,
                        "Python bindings for libgit2.");
@@ -1823,6 +2055,9 @@ initpygit2(void)
     Py_INCREF(&IndexEntryType);
     PyModule_AddObject(m, "IndexEntry", (PyObject *)&IndexEntryType);
 
+    Py_INCREF(&ReferenceType);
+    PyModule_AddObject(m, "Reference", (PyObject *)&ReferenceType);
+
     PyModule_AddIntConstant(m, "GIT_OBJ_ANY", GIT_OBJ_ANY);
     PyModule_AddIntConstant(m, "GIT_OBJ_COMMIT", GIT_OBJ_COMMIT);
     PyModule_AddIntConstant(m, "GIT_OBJ_TREE", GIT_OBJ_TREE);
@@ -1832,4 +2067,7 @@ initpygit2(void)
     PyModule_AddIntConstant(m, "GIT_SORT_TOPOLOGICAL", GIT_SORT_TOPOLOGICAL);
     PyModule_AddIntConstant(m, "GIT_SORT_TIME", GIT_SORT_TIME);
     PyModule_AddIntConstant(m, "GIT_SORT_REVERSE", GIT_SORT_REVERSE);
+    PyModule_AddIntConstant(m,"GIT_REF_OID", GIT_REF_OID);
+    PyModule_AddIntConstant(m,"GIT_REF_SYMBOLIC", GIT_REF_SYMBOLIC);
+    PyModule_AddIntConstant(m,"GIT_REF_PACKED", GIT_REF_PACKED);
 }
diff --git a/test/__init__.py b/test/__init__.py
index 93e908f..cebf864 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -35,7 +35,8 @@ import sys
 import unittest
 
 
-names = ['blob', 'commit', 'index', 'repository', 'revwalk', 'tag', 'tree']
+names = ['blob', 'commit', 'index', 'refs', 'repository', 'revwalk', 'tag',
+         'tree']
 def test_suite():
     modules = ['test.test_%s' % n for n in names]
     return unittest.defaultTestLoader.loadTestsFromNames(modules)
diff --git a/test/test_refs.py b/test/test_refs.py
new file mode 100644
index 0000000..52e615e
--- /dev/null
+++ b/test/test_refs.py
@@ -0,0 +1,97 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+#
+# Copyright 2011 Itaapy
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License, version 2,
+# as published by the Free Software Foundation.
+#
+# In addition to the permissions in the GNU General Public License,
+# the authors give you unlimited permission to link the compiled
+# version of this file into combinations with other programs,
+# and to distribute those combinations without any restriction
+# coming from the use of this file.  (The General Public License
+# restrictions do apply in other respects; for example, they cover
+# modification of the file, and distribution when not linked into
+# a combined executable.)
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING.  If not, write to
+# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+"""Tests for reference objects."""
+
+
+__author__ = 'david.versmisse@itaapy.com (David Versmisse)'
+
+import unittest
+import utils
+from pygit2 import GIT_REF_OID
+
+
+
+LAST_COMMIT = '2be5719152d4f82c7302b1c0932d8e5f0a4a0e98'
+
+
+
+class ReferencesTest(utils.RepoTestCase):
+
+    def test_list_all_references(self):
+        self.assertEqual(self.repo.listall_references(),
+                         ('refs/heads/i18n', 'refs/heads/master'))
+
+
+    def test_lookup_reference(self):
+        repo = self.repo
+
+        # Raise KeyError ?
+        self.assertRaises(KeyError, repo.lookup_reference, 'foo')
+
+        # Test a lookup
+        reference = repo.lookup_reference('refs/heads/master')
+        self.assertEqual(reference.name, 'refs/heads/master')
+
+
+    def test_reference_get_sha(self):
+        reference = self.repo.lookup_reference('refs/heads/master')
+        self.assertEqual(reference.sha, LAST_COMMIT)
+
+
+    def test_reference_get_type(self):
+        reference = self.repo.lookup_reference('refs/heads/master')
+        self.assertEqual(reference.type, GIT_REF_OID)
+
+
+    def test_get_target(self):
+        # XXX We must have a symbolic reference to make this test
+        pass
+
+
+    def test_reference_resolve(self):
+        # XXX We must have a symbolic reference to make a better test
+        reference = self.repo.lookup_reference('refs/heads/master')
+        reference = reference.resolve()
+        self.assertEqual(reference.type, GIT_REF_OID)
+        self.assertEqual(reference.sha, LAST_COMMIT)
+
+
+    def test_create_reference(self):
+        # We add a tag as a new reference that points to "origin/master"
+        reference = self.repo.create_reference('refs/tags/version1',
+                                               LAST_COMMIT)
+        refs = self.repo.listall_references()
+        self.assertTrue('refs/tags/version1' in refs)
+        reference = self.repo.lookup_reference('refs/tags/version1')
+        self.assertEqual(reference.sha, LAST_COMMIT)
+
+
+
+if __name__ == '__main__':
+    unittest.main()