bos@159: \chapter{Collaborating with other people} bos@159: \label{cha:collab} bos@159: bos@159: As a completely decentralised tool, Mercurial doesn't impose any bos@159: policy on how people ought to work with each other. However, if bos@159: you're new to distributed revision control, it helps to have some bos@159: tools and examples in mind when you're thinking about possible bos@159: workflow models. bos@159: bos@159: \section{Collaboration models} bos@159: bos@159: With a suitably flexible tool, making decisions about workflow is much bos@159: more of a social engineering challenge than a technical one. bos@159: Mercurial imposes few limitations on how you can structure the flow of bos@159: work in a project, so it's up to you and your group to set up and live bos@159: with a model that matches your own particular needs. bos@159: bos@159: \subsection{Factors to keep in mind} bos@159: bos@159: The most important aspect of any model that you must keep in mind is bos@159: how well it matches the needs and capabilities of the people who will bos@159: be using it. This might seem self-evident; even so, you still can't bos@159: afford to forget it for a moment. bos@159: bos@159: I once put together a workflow model that seemed to make perfect sense bos@159: to me, but that caused a considerable amount of consternation and bos@159: strife within my development team. In spite of my attempts to explain bos@159: why we needed a complex set of branches, and how changes ought to flow bos@159: between them, a few team members revolted. Even though they were bos@159: smart people, they didn't want to pay attention to the constraints we bos@159: were operating under, or face the consequences of those constraints in bos@159: the details of the model that I was advocating. bos@159: bos@159: Don't sweep foreseeable social or technical problems under the rug. bos@159: Whatever scheme you put into effect, you should plan for mistakes and bos@159: problem scenarios. Consider adding automated machinery to prevent, or bos@159: quickly recover from, trouble that you can anticipate. As an example, bos@159: if you intend to have a branch with not-for-release changes in it, bos@159: you'd do well to think early about the possibility that someone might bos@159: accidentally merge those changes into a release branch. You could bos@159: avoid this particular problem by writing a hook that prevents changes bos@159: from being merged from an inappropriate branch. bos@159: bos@159: \subsection{Informal anarchy} bos@159: bos@159: I wouldn't suggest an ``anything goes'' approach as something bos@159: sustainable, but it's a model that's easy to grasp, and it works bos@159: perfectly well in a few unusual situations. bos@159: bos@159: As one example, many projects have a loose-knit group of collaborators bos@159: who rarely physically meet each other. Some groups like to overcome bos@159: the isolation of working at a distance by organising occasional bos@159: ``sprints''. In a sprint, a number of people get together in a single bos@159: location (a company's conference room, a hotel meeting room, that kind bos@159: of place) and spend several days more or less locked in there, hacking bos@159: intensely on a handful of projects. bos@159: bos@159: A sprint is the perfect place to use the \hgcmd{serve} command, since bos@159: \hgcmd{serve} does not requires any fancy server infrastructure. You bos@159: can get started with \hgcmd{serve} in moments, by reading bos@159: section~\ref{sec:collab:serve} below. Then simply tell the person bos@159: next to you that you're running a server, send the URL to them in an bos@159: instant message, and you immediately have a quick-turnaround way to bos@159: work together. They can type your URL into their web browser and bos@159: quickly review your changes; or they can pull a bugfix from you and bos@159: verify it; or they can clone a branch containing a new feature and try bos@159: it out. bos@159: bos@159: The charm, and the problem, with doing things in an ad hoc fashion bos@159: like this is that only people who know about your changes, and where bos@159: they are, can see them. Such an informal approach simply doesn't bos@159: scale beyond a handful people, because each individual needs to know bos@159: about $n$ different repositories to pull from. bos@159: bos@159: \subsection{A single central repository} bos@159: bos@159: For smaller projects, migrating from a centralised revision control bos@159: tool, perhaps the easiest way to get started is to have changes flow bos@159: through a single shared central repository. This is also the bos@159: most common ``building block'' for more ambitious workflow schemes. bos@159: bos@159: Contributors start by cloning a copy of this repository. They can bos@159: pull changes from it whenever they need to, and some (perhaps all) bos@159: developers have permission to push a change back when they're ready bos@159: for other people to see it. bos@159: bos@159: Under this model, it can still sometimes make sense for people to pull bos@159: changes directly from each other, without going through the central bos@159: repository. Consider a case in which I have a tentative bug fix, but bos@159: I am worried that if I were to publish it to the central repository, bos@159: it might subsequently break everyone else's trees as they pull it. To bos@159: reduce the potential for damage, I can ask you to clone my repository bos@159: into a temporary repository of your own and test it. This lets us put bos@159: off publishing the potentially unsafe change until it has had a little bos@159: testing. bos@159: bos@159: In this kind of scenario, people usually use the \command{ssh} bos@159: protocol to securely push changes to the central repository, as bos@159: documented in section~\ref{sec:collab:ssh}. It's also usual to bos@159: publish a read-only copy of the repository over HTTP using CGI, as in bos@159: section~\ref{sec:collab:cgi}. Publishing over HTTP satisfies the bos@159: needs of people who don't have push access, and those who want to use bos@159: web browsers to browse the repository's history. bos@159: bos@159: \subsection{The Linux kernel model} bos@159: bos@159: The development of the Linux kernel has a shallow hierarchical bos@159: structure, surrounded by a cloud of apparent chaos. Because most bos@159: Linux developers use \command{git}, a distributed revision control bos@159: tool with capabilities similar to Mercurial, it's useful to describe bos@159: the way work flows in that environment; if you like the ideas, the bos@159: approach translates well across tools. bos@159: bos@159: At the center of the community sits Linus Torvalds, the creator of bos@159: Linux. He publishes a single source repository that is considered the bos@159: ``authoritative'' current tree by the entire developer community. bos@159: Anyone can clone Linus's tree, but he is very choosy about whose trees bos@159: he pulls from. bos@159: bos@159: Linus has a number of ``trusted lieutenants''. As a general rule, he bos@159: pulls whatever changes they publish, in most cases without even bos@159: reviewing those changes. Some of those lieutenants are generally bos@159: agreed to be ``maintainers'', responsible for specific subsystems bos@159: within the kernel. If a random kernel hacker wants to make a change bos@159: to a subsystem that they want to end up in Linus's tree, they must bos@159: find out who the subsystem's maintainer is, and ask that maintainer to bos@159: take their change. If the maintainer reviews their changes and agrees bos@159: to take them, they'll pass them along to Linus in due course. bos@159: bos@159: Individual lieutenants have their own approaches to reviewing, bos@159: accepting, and publishing changes; and for deciding when to feed them bos@159: to Linus. In addition, there are several well known branches that bos@159: people use for different purposes. For example, a few people maintain bos@159: ``stable'' repositories of older versions of the kernel, to which they bos@159: apply critical fixes as needed. bos@159: bos@159: This model has two notable features. The first is that it's ``pull bos@159: only''. You have to ask, convince, or beg another developer to take a bos@159: change from you, because there are no shared trees, and there's no way bos@159: to push changes into a tree that someone else controls. bos@159: bos@159: The second is that it's based on reputation and acclaim. If you're an bos@159: unknown, Linus will probably ignore changes from you without even bos@159: responding. But a subsystem maintainer will probably review them, and bos@159: will likely take them if they pass their criteria for suitability. bos@159: The more ``good'' changes you contribute to a maintainer, the more bos@159: likely they are to trust your judgment and accept your changes. If bos@159: you're well-known and maintain a long-lived branch for something Linus bos@159: hasn't yet accepted, people with similar interests may pull your bos@159: changes regularly to keep up with your work. bos@159: bos@159: Reputation and acclaim don't necessarily cross subsystem or ``people'' bos@159: boundaries. If you're a respected but specialised storage hacker, and bos@159: you try to fix a networking bug, that change will receive a level of bos@159: scrutiny from a network maintainer comparable to a change from a bos@159: complete stranger. bos@159: bos@159: To people who come from more orderly project backgrounds, the bos@159: comparatively chaotic Linux kernel development process often seems bos@159: completely insane. It's subject to the whims of individuals; people bos@159: make sweeping changes whenever they deem it appropriate; and the pace bos@159: of development is astounding. And yet Linux is a highly successful, bos@159: well-regarded piece of software. bos@159: bos@159: \section{The technical side of sharing} bos@159: bos@159: \subsection{Informal sharing with \hgcmd{serve}} bos@159: \label{sec:collab:serve} bos@159: bos@159: Mercurial's \hgcmd{serve} command is wonderfully suited to small, bos@159: tight-knit, and fast-paced group environments. It also provides a bos@159: great way to get a feel for using Mercurial commands over a network. bos@159: bos@159: Run \hgcmd{serve} inside a repository, and in under a second it will bos@159: bring up a specialised HTTP server; this will accept connections from bos@159: any client, and serve up data for that repository until you terminate bos@159: it. Anyone who knows the URL of the server you just started, and can bos@159: talk to your computer over the network, can then use a web browser or bos@159: Mercurial to read data from that repository. A URL for a bos@159: \hgcmd{serve} instance running on a laptop is likely to look something bos@159: like \Verb|http://my-laptop.local:8000/|. bos@159: bos@159: The \hgcmd{serve} command is \emph{not} a general-purpose web server. bos@159: It can do only two things: bos@159: \begin{itemize} bos@159: \item Allow people to browse the history of the repository it's bos@159: serving, from their normal web browsers. bos@159: \item Speak Mercurial's wire protocol, so that people can bos@159: \hgcmd{clone} or \hgcmd{pull} changes from that repository. bos@159: \end{itemize} bos@159: In particular, \hgcmd{serve} won't allow remote users to \emph{modify} bos@159: your repository. It's intended for read-only use. bos@159: bos@159: If you're getting started with Mercurial, there's nothing to prevent bos@159: you from using \hgcmd{serve} to serve up a repository on your own bos@159: computer, then use commands like \hgcmd{clone}, \hgcmd{incoming}, and bos@159: so on to talk to that server as if the repository was hosted remotely. bos@159: This can help you to quickly get acquainted with using commands on bos@159: network-hosted repositories. bos@159: bos@159: \subsubsection{A few things to keep in mind} bos@159: bos@159: Because it provides unauthenticated read access to all clients, you bos@159: should only use \hgcmd{serve} in an environment where you either don't bos@159: care, or have complete control over, who can access your network and bos@159: pull data from your repository. bos@159: bos@159: The \hgcmd{serve} command knows nothing about any firewall software bos@159: you might have installed on your system or network. It cannot detect bos@159: or control your firewall software. If other people are unable to talk bos@159: to a running \hgcmd{serve} instance, the second thing you should do bos@159: (\emph{after} you make sure that they're using the correct URL) is bos@159: check your firewall configuration. bos@159: bos@159: By default, \hgcmd{serve} listens for incoming connections on bos@159: port~8000. If another process is already listening on the port you bos@159: want to use, you can specify a different port to listen on using the bos@159: \hgopt{serve}{-p} option. bos@159: bos@159: Normally, when \hgcmd{serve} starts, it prints no output, which can be bos@159: a bit unnerving. If you'd like to confirm that it is indeed running bos@159: correctly, and find out what URL you should send to your bos@159: collaborators, start it with the \hggopt{-v} option. bos@159: bos@159: \subsection{Using \command{ssh} as a tunnel} bos@159: \label{sec:collab:ssh} bos@159: bos@159: \subsection{Serving HTTP with a CGI script} bos@159: \label{sec:collab:cgi} bos@159: bos@159: bos@159: bos@159: %%% Local Variables: bos@159: %%% mode: latex bos@159: %%% TeX-master: "00book" bos@159: %%% End: