If you’re using Kiln’s branch repositories to separate development of different features and version, as we do at Fog Creek, it can be hard to keep track of what repositories contain certain fixes and features. One of your developers might have an awesome new feature in her own branch, along with a bug fix that’s gone to QA. Plus, another developer just pushed a feature right to your release repository! How can you keep all this straight?

The Related Graph, new in Kiln 2.4, is designed to answer these questions. While the electric DAG shows you the relationship of changesets within a single repository, that doesn’t help much for showing the relationship of several related repositories. The Related Graph also shows a DAG, but it shows all the changesets in a set of related repositories. This means that every branch and other repository that shares history with the current repository is included — it’s the union of all those changesets. For large projects, this could get complicated, so Kiln simplifies the DAG by only showing the changesets that are a head in one or more repositories. All other changesets are collapsed into a single row. You can find the Related Graph by clicking the “Related” tab at the top of any repository, then clicking “Related”:

That sounds complicated, so let’s look at some more pictures!

First, let’s look at the simplest case: a single-headed repository with no branches.

(the repository I’m using here is jespern’s Piston for Django if you’d like to follow along at home)

It’s pretty straightforward: only the head is shown, and the other 264 changesets are collapsed into a single row. Now let’s push two changesets into the branch issue117 of our trunk repository to fix a bug:

two heads

Again, all the changesets except the two heads are collapsed. But why aren’t all the changesets collapsed into a single row? It’s because the Related Graph preserves the relationship of changesets to one another and to the repositories containing them. Remember that in the DAG, each changeset appears above its parents and other ancestors. So the ancestors of trunks‘s head, “Fixed Resource.error_handler to include em_format.”, are the 16 changesets and 248 changesets below it. The head in issue117 and the 1 changeset below that are not ancestors of trunk‘s head, so they are not collapsed into one row. In the same way, the ancestors of issue117‘s head are the 1 changeset and 248 changesets collapsed into two rows.

Put another way, trunk and issue117 share the first 248 changesets of their history. At this point, the repositories diverge. trunk has 17 changesets (16 collapsed + 1 head) that are not in issue117, and issue117 has 2 changesets (1 collapsed + 1 head) that are not in trunk. You can confirm this by clicking trunk‘s head to electrify it:

small electric

As expected, the ancestors of that changeset are the 264 collapse changesets; the changesets that are only in issue117 are not included. Let’s merge the branch into trunk:

merged branch

Now, issue117 hasn’t changed (as we only pushed to trunk), but trunk‘s head is now a merge. Its old head (and a couple other changesets) have been collapsed into the “19 changesets” row (you can click that to see exactly what changesets are collapsed there, in beautiful electrified style). Since the branch has been merged into trunk, issue117‘s head and it’s other changeset are now an ancestor of trunk‘s head, just like you’d expect. At this point, you could delete issue117, certain that all changesets in the branch have made it to another repository. Or, keep the branch around and you’ll always be able to come back to this graph and see exactly what changesets were initially in that branch — here, just the two changesets necessary to fix the bug. With Kiln, you never lose your history!

Let’s keep moving. Now, another developer has pushed his changes into another repository:

third branch

Much like before, you can see that Rocca shares the first 248 changesets with trunk, and then diverges for 3 changesets to its own head. But what if we push another head to Rocca?

three merged

Whoa! What’s going on here? Rocca now has another head, in addition to the one we saw in the last image. The new head, “adding jiaaro to authors”, is committed directly on top of trunk‘s head, so there are no intervening changesets to collapse. It’s easy to see that Rocca is a “more developed” branch than trunk — it includes all of trunk‘s changesets (and issue117‘s, for that matter), plus 4 additional ones.

Now, we want to ship all of these changes, so we merge the two heads from Rocca and push that to trunk:

two-headed branch

The two heads in Rocca are still marked as heads (by the green bubbles at the changesets), but they are both ancestors of the new head of trunk. The merge itself has been collapsed into the “1 changeset” row near the top, but it’s still a merge – you can trace that its two parents are the two heads in Rocca, just like you’d expect.

At the top of the page, you can see all the repositories that are included in the graph. Note that even though Rocca is a central repository, it’s included because it shares history with trunk and issue117. You can uncheck any that you don’t want to see:

uncheck branch

Though the head in issue117 is no longer shown, the changesets in issue117 are still there, since it was merged into trunk. You can see that the number of collapsed changesets in several of the rows have gone up to include the hidden changesets.

That covers all the bases for what the Related Graph can do. I’ll leave you with a more complicated example:

version branches with devel

This is the sort of graph you’ll see for a more mature product, set up with a branch per version plus development branches for each developer. Here, 0-5 is the oldest repository, and all of its changes are included in every other repository. Working up the DAG, each versioned repository shares most or all of its history with later versions. The collapsed rows represent all of the development between versions. For example, click the “271 changesets” between 0-8 and 0-7-1 to see all the changes that were done for the 0.8, 0.8.1, and 0.8.2 releases. Tracking your product’s history has never been easier!

At the top of the graph, it diverges as developers do new work in the devel repository and in their personal branches (hugo and jon). A quick electrification reveals that Jon’s changes are based on devel, including everything in the older versions; the only changes he’s missing are the three in Hugo’s branch and the two old ones in 0-6.

As the developers merge work back into devel, that repository’s head will move further from 0-8. When the 0.9 release is made, the head for 0-9 will appear between 0-8 and devel, and development will continue.

Understanding your code’s history requires looking across repositories to get the whole story. Kiln’s Related Graph helps you keep track of what changes are lingering in a developer’s personal branch or waiting to be pushed from a bugfix branch, and reveals the interconnected history of a large project. The shape of your project’s history is simplified, so you can understand your code base at a glance.