How to use git and GitHub with Pharo

Update 2017: This guide remains here for historical reasons. I no longer recommend using GitFileTree, you should jump straight into using Iceberg.


As far as I can tell (at the time of the writing anyway), there really isn’t any good (or bad for that matter) guide on how to use git(filetree) in Pharo, and since I had to explain it to several people already, I might as well write it down…

Going onward I will assume that you have some basic knowledge of git — concepts like commit, push/pull, merging, cloning; if not, then do yourself a favor and look up some tutorial.

Likewise, I will assume that you have git installed, including an appropriate git client:

As knowing git is basic knowledge, I will just link to git-only steps and/or mention only some tips or differences.

Creating a new repository

Creating a GitHub repository

Creating a new repo on GitHub is dead simple (and covered by GitHub’s help: Create A Repo).

Creating a new repo

So head over to GitHub, click on the + in top right corner, enter the desired name (1), initialize with README.md file (2) (you can add that later too), and optionally add a default .gitignore file appropriate for Smalltalk — mostly useful if you have dev image in the same folder as the repo itself.

Cloning

As git is distributed versioning, you will need a local clone of the repo, so instead of committing directly to the mainline in the cloud (which is fun when you don’t have network connection, or smalltalkhub is down), you commit instead to your local clone, and from there you can push to github or other places.

So copy the clone url and paste it into your client of choice — again, best to follow the official docs on cloning a repository.

Using gitfiletree

Now we finally get to use Pharo.

First of all, we will need to install GitFileTree, which can be done from the Catalog Browser.

catalog-browser.png

Creating a new GitFileTree repository

I highly recommend that you create a subdirectory where the code itself will be stored. I like to use repository, in other languages (java, C, etc.) you might encounter src. Although you don’t have to do this, it is very helpful for organizing your files, as you will likely have other files in your repo such as documentation, assets, license, etc.

GitHub repo overview with `repository` and other artifacts

To create the repository in Pharo, from World Menu open Monticello Browser and click on +Repository, you should see a new entry gitfiletree://, click on it.

new-monticello-repo.png

A file dialog will appear (left new File Dialog, right old Morphic File Dialog). Note that you should navigate into the target directory, so in both images you have to go one level deeper into the repository directory.

choose-directory-3.png

And you are done! Now you can use it exactly the same way as you would a regular Monticello repo — associating it with packages, committing, etc.

repo-created.png

If you don’t know how to actually work with Monticello (i.e. you are new to Pharo), we have that covered in the Chapter 8 of Pharo By Example book.

Defining a BaselineOf

A BaselineOf is a variation of ConfigurationOf specific for git projects. You would use the old ConfigurationOf to manage not just the project’s dependencies, but also the versions (which I personally found nightmare-inducing). Because git tracks the versions by itself, we can completely ignore this and define just the dependencies.

So if you have no dependencies, you can have something like this.

1
2
3
4
5
6
7
8
BaselineOf subclass: #BaselineOfFileDialog
BaselineOfFileDialog>>baseline: spec
<baseline>
spec
for: #common
do: [ spec package: 'FileDialog'.
spec group: 'default' with: #('FileDialog') ]

If you want more details on baselines, you can read Uko’s Pharo and Git(Hub) Versioning.

Loading existing repository

If you already a have gitfiletree repository, and you just want to load it into Pharo, you can do so in two ways.

The first one is pretty much the same as above, you open Monticello Browser, add the repo and manually load the packages.

The second one makes use of Metacello. This will however only work if you have already created a BaselineOf.

With baseline, you can just do

Loading local gitfiletree repo
1
2
3
4
Metacello new
baseline: 'FileDialog';
repository: 'gitfiletree:///home/peter/prog/file-dialog/repository';
load

Do not forget the /repository at the end if you have created a subdirectory for the code!

Overriding baselines

Sometimes you a project has been loaded as a BaselineOf/ConfigurationOf dependency, or you loaded it through the github:// protocol, e.g.

1
2
3
4
Metacello new
baseline: 'FileDialog';
repository: 'github://peteruhnak/file-dialog/repository';
load.

Unfortunately this doesn’t actually use git in the way you would expect. The github:// protocol merely downloads a zip from GitHub and loads whatever was there. You cannot commit back.

What’s worse, if you now try to load the proper Metacello gitfiletree repo, you will get an error: Load Conflict between existing BaselineOfFileDialog [baseline] from github://… and BaselineOfFileDialog [baseline] from gitfiletree:///…

That’s because Metacello thinks they are different repositories. To solve this, you need to tell Metacello that you are ok with the conflict.

1
2
3
4
5
Metacello new
baseline: 'FileDialog';
repository: 'gitfiletree:///home/peter/prog/file-dialog/repository';
onConflict: [ :ex | ex allow ];
load

Pushing/pulling

To push to GitHub (or pull from), you can either use your git client, or do so directly from within Pharo by clicking on the “Pull” and “Push” buttons in repository detail.

pull.png

Remote git repository

If you want to skip some hassle of cloning, you can use remote git repository. This will automatically clone the repository to the image’s directory (if you have sufficient permissions for it).

remote-git-repo.png
Cloning remote git repo
1
2
3
4
5
MCFileTreeGitRemoteRepository
location: 'git@github.com:peteruhnak/xmi-analyzer.git'
name: 'local-name'
subdirectory: 'repository'
branch: 'master'

The location is the location of your repository (you can copy the link from the repo’s GitHub page), name is a name of the folder where the repository will be automatically cloned (imageDirectory/name), subdirectory the subdirectory containing the code, and finally branch the git branch (if left empty, master is assumed).

Keep in mind that you need to have your SSH keys configured for this.

Copying existing project from SmalltalkHub

If you already have a project on SmalltalkHub and you would like to move over to GitHub, I’ve written a simple guide some time ago: Moving project from SmalltalkHub to GitHub.

Iceberg

Now that I’ve somewhat covered GitFileTree, I am obligated to mention Iceberg.

GitFileTree is pretty much an attempt to fit git into an existing Monticello infrastructure. Although it works somewhat, there is no real git tooling support and there are inherent incompatibilites and shortcommings (such as branch support).

Iceberg on the other hand is aiming for a proper git support, including a set of appropriate tools (so essentially a proper git client, but within Pharo). The project is still quite young and unstable, but as it is the future of git in Pharo, you should keep an eye on it.

What’s more, you can use metadataless GitFileTree and Iceberg more-or-less side by side, so you can already experiment a bit (but keep in mind that it’s still unstable, and it will break).

Testing with Travis

With the repo on GitHub good to go, you might also take a look at the following: