[cairo] Maintaining cairo with git

Carl Worth cworth at cworth.org
Thu Feb 16 17:54:00 PST 2006

It's official now.

I've switched all of my work on cairo from CVS to git. For now, there
is no way to commit to the cairo from the cvs client, (but we may be
able to set that up soon if using cogito or git would be a
deal-breaker for anyone wanting to commit---please let me know).

I assume that for many interested parties, this will be a first
exposure to git, (this is all new to me), so I'll cover a fair bit of
tutorial information in this email.

The first two sections below (Repository locations and Getting git)
apply to anyone who is interested in working with the latest cairo
source from here on out. The remaining "How to" sections describe
various things one might want to do. So pick and choose which you want
to read based on what you want to do. In each I'll recommend git or
cogito as I think best fits the task, though one might use either in
any case.

I think this is going to be a great change for cairo, and I hope
people will be patient with any pain caused by the transition.


PS. We'll need to get a bunch of web pages updated as well, and I
would be glad for any help anyone could offer there, (no permission
needed---just go fix the wiki-based content of

Repository locations
The repository for "central" cairo development, (that is, what
releases will be made from), is here:


I am also publishing a personal repository which will contain many
branches that won't appear in the above repository. These branches
will have my in-progress development, patches for open bugzilla
entries, and in-progress development that others are doing that I've
looked at. This repository exists here:


This ability to advertise in-progress development in this way is
something I'm very excited about. As others publish similar personal
repositories (some notes on this below) I think we'll see great
improvements in the speed of cairo development. This will come from
increased visibility and more direct support for sharing code that
doesn't yet exist centrally.

Getting git (and cogito)
In order to start using these new repositories, people will need to
get a git-capable client. The two that I discuss here are: as git-core
and cogito and have respective command-line prefixes of git and cg.

It's probably best to just install both, and after reading a bit and
playing with both, deciding which one you might prefer to use.

Most current distributions should have packages readily
available. (Note: There's a potential package name clash with 'GNU
interactive tools' so you might need a "git-core" package rather than
"git", but "cogito" is "cogito" pretty much everywhere).

I do recommend running a recent version of git (at least 1.2.0).

If you can't get a reasonable packages from your distribution, you can
get tar files from:


	(See .sign files in the same directories to confirm integrity.)

How to track the latest cairo development (cogito)
This is quite easy. It's an initial clone:

	cg-clone git://git.cairographics.org/cairo

followed by periodic updates:


run from within the resulting cairo directory. This should work just
as easily as a traditional cvs checkout and periodic cvs updates.

How to browse around a repository
A nice thing about git is that the tools for exploring the repository
are so much better than they are with cvs. After you've got a cloned
repository, change into the cairo directory and run:

	gitk --all

That's a very handy tool. The Tcl/Tk graphics are fairly ugly, but
fortunately a new cairo-based rewrite named gitview is being worked
on, (as recently seen on this list).

Meanwhile, we've also web-based repository browsing available:


How to commit to cairo in a central way, just like we used to with cvs
I think cogito is the best tool to use to make the migration from cvs
as easy as possible. It's little more than remembering to type 'cg-'
instead of 'cvs '. (Hey, you get to save one keypress per command and
you gain tab-completion!).

To get started, first change the clone command above to use the
git+ssh protocol which is required to be able to push changes back:

	cg-clone git+ssh://git.cairographics.org/cairo

(If you did a non-git+ssh clone previously, you can simply edit the
URL in cairo/.git/remotes/origin to add the "+ssh" piece.)

Then, development looks a lot like it does with cvs:

	# edit some stuff
	cg-add new-file
	cg-rm old-file

The only big change is that the cg-commit just makes a local commit,
(and this is a huge feature---you can now do all the offline commits
you want). So to actually push your new commits out the the central
repository, you need to remember to do:


Updating is, as expected, as simple as:


I personally haven't done a lot of merging yet with cogito, but the
cogito author promises that it will just tell you what to do and that
everything in cogito is designed to make the migration for cvs as easy
as possible:

	Cogito turbo-introduction

WARNING: It appears that cg-commit is happy to commit files with
conflict markers left in them. This may be surprising to users of cvs.

How to commit to cairo in a central way with git, instead of cogito
I said before that cogito is likely the best tool to use for someone
that just wants to commit to cairo in a central, cvs-like way.

But it's not really any harder to use the git client to do the same
thing. There's a bit more variation from cvs in the command naming,
and there are some additional conceptual underpinnings to some of the
commands (there's a learning opportunity here).

But you don't have to learn any more to get started. First clone the
repository with git, and using the git+ssh protocol:

	git clone git+ssh//git.cairographics.org/cairo

Then, development looks a bit like cvs, but with a couple extra
command-line arguments here and there:

	# edit some stuff
	git add new-file
	git status -a
	git diff HEAD
	git commit -a

Notice that there is no equivalent to "cvs rm" here. When you use
"git commit -a" file removals get picked up automatically.

As mentioned in the cogito example above, with git the commit happens
locally, so there's an extra command needed (compared to working with
cvs) in order to push things out to the central repository:

	git push origin

And to get other people's commits from the central repository, there's
a corresponding command:

	git pull

This does a similar job as "cvs update" or "cg-update" but it has a
name that matches git's push command quite nicely.

It can happen that git pull results in a conflict, and it will put
conflict markers in the local files. In this case git status will
indicate that files are in an "unmerged" state. Once the conflicts
have all been manually resolved, you can "git commit -a"

WARNING: It appears that cg-commit is happy to commit files with
conflict markers left in them. This may be surprising to users of cvs.

For a bit more on working with git, you might see the following

	A tutorial introduction to git

How to make sense of the giant hex strings I keep seeing in git
[Note: From here on out in this email, one could likely use cogito to
perform each of the tasks described, and that might even be easier in
some cases. But I've been learning git, so I'll be showing what I've
learned so far.]

Here's a tiny detour into the elegant guts of git. At the backend of
git is a content-addressable object store in which all objects are
named by the SHA1 hash of their contents.

The most elementary object type is a "blob", which simply contains the
contents of a file. The next higher-level object type is a "tree"
which contains a list of files (name, execute permission, and blob),
or other tree objects. Then there is a "commit" object which contains
a tree as well as one or parent commit objects. Finally, there is a
"tag" object which attaches a symbolic identifier to an object, (and
can optionally be signed).

So, objects are regularly referred to by the names git knows them by,
these SHA1 hash values, which are long sequences of hex digits.
They're not as scary as one might think. One thing that helps is that
unique prefixes will be accepted by git. So passing along the first 8
or 10 characters, say, works for casual short-term use. For long-term
use, tags provide ways to attach easy-to-remember names to interesting
SHA1 values.

How to work with branches in git
Within git, there is the notion of a "current branch". As you might
guess, this is simply a reference to a commit object. And when a new
"commit" operation is performed, the current branch's commit object
becomes the parent of the new commit object, and the branch is updated
to refer to the new commit object.

There is a simple command to list existing branches as well as the
current branch (marked with a *):

	git branch

This command also allows for the creation of a new branch pointing at
the same commit as the current branch:

	git branch new-branch

There is a separate command, "checkout", to switch to a different

	git checkout new-branch

This command will not succeed if you have local, uncommitted
modifications to files, but you can force it to throw them away with
-f or merge them into the destination branch with -m.

The common operation of "make a new branch and switch to it", (the
combination of the above two commands), can be performed with:

	git checkout -b new-branch

You'll notice that after a new clone, the current branch is named
'master' and there's another branch named 'origin' that shows where
the remote repositories 'master' branch was when you cloned. This
relationship between remote master and local origin is established by
the following line in the .git/remotes/origin file which the clone
operation creates:

	Pull: master:origin

Now that you know how to change the current branch, it's important to
understand a bit more about what "git pull" does. The pull operation
is the same as first doing a "git fetch" of the remote branch, (which
simply fetches the new commits along that branch), and then also doing
a "git merge" of the current branch into the local mapping of the
remote branch.

The important thing to notice here is that "git pull" is potentially
merging *and* that "git pull" depends on the current branch. So, with
the above master:origin mapping, you will usually want to make sure
you are on your local "master" branch before doing a "git pull" of the
origin's master branch, (which is what "git pull" does by default).

That is, if you start changing branches, then "update to all the
latest commits" will now usually look like:

	git checkout master; git pull

rather than just "git pull".

New branches are very useful for working on independent lines of
development. And there basically free with git, so it makes sense to
use them heavily. It might make sense to establish a pattern as
follows before writing new code to do some-interesting-thing.

	1. Get up-to-date with the latest commits from others

	git checkout master; git pull

	2. Make a new branch and switch to it:

	git checkout -b some-interesting-thing

How to maintain a personal branch on git.cairographics.org
[Note: I was trying to write some short notes on
cairo-project-specific ways of using git, but I ended up with all the
above background. Oh well, at least that makes this message fairly
well self-contained. But here, finally, is the part that I think is
the most interesting.]

I think it's going to take some experimenting to find out what kinds
of git usage make the most sense for the cairo project. There's a lot
of flexibility and a lot of room for us to collectively find our own

But here's a proposal for a starting point at least. I'll show you how
to setup your tree in a similar way to mine, which allows for pushing
commits of things that are "ready" to the central tree and allows for
pushing of lots of crazy branches to a personal tree.

First, on git.cairographics.org, any cairo maintainer can host their
own tree if they would like to. We don't yet have a way for people to
create their own repositories there, (the shell is locked down to
allow only git clone, push, pull, etc.). So you'll just have to ask me
if you want one. I did go ahead an create repositories for anyone who
has committed to cairo within the last three months, which turns out
to be:

	andersca, behdad, cworth, biesi, davidr, emmanuel, keithp,
	memmel, pavlov, and vladimir

So, to get started I suggest cloning from the central tree:

	git clone git+ssh://git.cairographics.org/git/cairo

and things that you want to push back to it should be committed to the
"master" branch locally and can then be pushed up with:

	git push origin

and as before, getting new commits from others is simply:

	git pull

Then, for publishing other branches in your personal repository, do
something like:

	echo "URL: git+ssh://git.cairographics.org/~$USER/cairo" > .git/remotes/$USER
	echo "Push: --all" >> .git/remotes/$USER

Now, as you do new development, do it on some branch first, (one
branch per topic will make it easier to merge independently as they
cook at different rates). And at any point you can publish all of
these branches by simply doing:

	git push $USER

Then if you want to look at someone else's changes, you can fetch an
individual branch of their's into your own tree with:

	git fetch git://git.cairographics.org/~user/cairo <branch>:<branch>

And you can setup a .git/remotes/<user> file to make common commands
like that as simple as "git fetch <user>"

OK, that's it from me now. There are lots of good git man pages, all
of which can also be found on the web here:


and other little goodies in the Documentation directory that comes in
the git source distribution. Plus the source of git itself can be
quite enlightening. Oh, and the git mailing list is fast, but
friendly, and doesn't require any registration:


Have fun with git and cairo!


PS. I wrote this all in one sitting, didn't read it, and didn't have
anyone else read it. So I'm certain it's broken in spots, (though I
did test cut-and-paste of most commands). Just holler when things seem
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20060216/cefd02e5/attachment.pgp

More information about the cairo mailing list