bos@559: bos@559: dongsheng@625: bos@572: bos@559: Collaborating with other people bos@559: bos@559: As a completely decentralised tool, Mercurial doesn't impose bos@559: any policy on how people ought to work with each other. However, bos@559: if you're new to distributed revision control, it helps to have bos@559: some tools and examples in mind when you're thinking about bos@559: possible workflow models. bos@559: bos@559: bos@559: Mercurial's web interface bos@559: bos@559: Mercurial has a powerful web interface that provides several bos@559: useful capabilities. bos@559: bos@559: For interactive use, the web interface lets you browse a bos@559: single repository or a collection of repositories. You can view bos@559: the history of a repository, examine each change (comments and bos@559: diffs), and view the contents of each directory and file. bos@559: bos@559: Also for human consumption, the web interface provides an bos@559: RSS feed of the changes in a repository. This lets you bos@559: subscribe to a repository using your favourite bos@559: feed reader, and be automatically notified of activity in that bos@559: repository as soon as it happens. I find this capability much bos@559: more convenient than the model of subscribing to a mailing list bos@559: to which notifications are sent, as it requires no additional bos@559: configuration on the part of whoever is serving the bos@559: repository. bos@559: bos@559: The web interface also lets remote users clone a repository, bos@559: pull changes from it, and (when the server is configured to bos@559: permit it) push changes back to it. Mercurial's HTTP tunneling bos@559: protocol aggressively compresses data, so that it works bos@559: efficiently even over low-bandwidth network connections. bos@559: bos@559: The easiest way to get started with the web interface is to bos@559: use your web browser to visit an existing repository, such as bos@559: the master Mercurial repository at http://www.selenic.com/repo/hg?style=gitweb. bos@559: bos@559: If you're interested in providing a web interface to your bos@559: own repositories, Mercurial provides two ways to do this. The bos@559: first is using the hg serve bos@559: command, which is best suited to short-term bos@559: lightweight serving. See section below for details of how to use bos@559: this command. If you have a long-lived repository that you'd bos@559: like to make permanently available, Mercurial has built-in bos@559: support for the CGI (Common Gateway Interface) standard, which bos@559: all common web servers support. See section for details of CGI bos@559: configuration. bos@559: bos@559: bos@559: bos@559: Collaboration models bos@559: bos@559: With a suitably flexible tool, making decisions about bos@559: workflow is much more of a social engineering challenge than a bos@559: technical one. Mercurial imposes few limitations on how you can bos@559: structure the flow of work in a project, so it's up to you and bos@559: your group to set up and live with a model that matches your own bos@559: particular needs. bos@559: bos@559: bos@559: Factors to keep in mind bos@559: bos@559: The most important aspect of any model that you must keep bos@559: in mind is how well it matches the needs and capabilities of bos@559: the people who will be using it. This might seem bos@559: self-evident; even so, you still can't afford to forget it for bos@559: a moment. bos@559: bos@559: I once put together a workflow model that seemed to make bos@559: perfect sense to me, but that caused a considerable amount of bos@559: consternation and strife within my development team. In spite bos@559: of my attempts to explain why we needed a complex set of bos@559: branches, and how changes ought to flow between them, a few bos@559: team members revolted. Even though they were smart people, bos@559: they didn't want to pay attention to the constraints we were bos@559: operating under, or face the consequences of those constraints bos@559: in the details of the model that I was advocating. bos@559: bos@559: Don't sweep foreseeable social or technical problems under bos@559: the rug. Whatever scheme you put into effect, you should plan bos@559: for mistakes and problem scenarios. Consider adding automated bos@559: machinery to prevent, or quickly recover from, trouble that bos@559: you can anticipate. As an example, if you intend to have a bos@559: branch with not-for-release changes in it, you'd do well to bos@559: think early about the possibility that someone might bos@559: accidentally merge those changes into a release branch. You bos@559: could avoid this particular problem by writing a hook that bos@559: prevents changes from being merged from an inappropriate bos@559: branch. bos@559: bos@559: bos@559: bos@559: Informal anarchy bos@559: bos@559: I wouldn't suggest an anything goes bos@559: approach as something sustainable, but it's a model that's bos@559: easy to grasp, and it works perfectly well in a few unusual bos@559: situations. bos@559: bos@559: As one example, many projects have a loose-knit group of bos@559: collaborators who rarely physically meet each other. Some bos@559: groups like to overcome the isolation of working at a distance bos@559: by organising occasional sprints. In a sprint, bos@559: a number of people get together in a single location (a bos@559: company's conference room, a hotel meeting room, that kind of bos@559: place) and spend several days more or less locked in there, bos@559: hacking intensely on a handful of projects. bos@559: bos@559: A sprint is the perfect place to use the hg serve command, since hg serve does not require any fancy bos@559: server infrastructure. You can get started with hg serve in moments, by reading dongsheng@625: section below. Then simply bos@559: tell bos@559: the person next to you that you're running a server, send the bos@559: URL to them in an instant message, and you immediately have a bos@559: quick-turnaround way to work together. They can type your URL bos@559: into their web browser and quickly review your changes; or bos@559: they can pull a bugfix from you and verify it; or they can bos@559: clone a branch containing a new feature and try it out. bos@559: bos@559: The charm, and the problem, with doing things in an ad hoc bos@559: fashion like this is that only people who know about your bos@559: changes, and where they are, can see them. Such an informal bos@559: approach simply doesn't scale beyond a handful people, because bos@559: each individual needs to know about $n$ different repositories bos@559: to pull from. bos@559: bos@559: bos@559: bos@559: A single central repository bos@559: bos@559: For smaller projects migrating from a centralised revision bos@559: control tool, perhaps the easiest way to get started is to bos@559: have changes flow through a single shared central repository. bos@559: This is also the most common building block for bos@559: more ambitious workflow schemes. bos@559: bos@559: Contributors start by cloning a copy of this repository. bos@559: They can pull changes from it whenever they need to, and some bos@559: (perhaps all) developers have permission to push a change back bos@559: when they're ready for other people to see it. bos@559: bos@559: Under this model, it can still often make sense for people bos@559: to pull changes directly from each other, without going bos@559: through the central repository. Consider a case in which I bos@559: have a tentative bug fix, but I am worried that if I were to bos@559: publish it to the central repository, it might subsequently bos@559: break everyone else's trees as they pull it. To reduce the bos@559: potential for damage, I can ask you to clone my repository bos@559: into a temporary repository of your own and test it. This bos@559: lets us put off publishing the potentially unsafe change until bos@559: it has had a little testing. bos@559: bos@559: In this kind of scenario, people usually use the bos@559: ssh protocol to securely push changes to bos@559: the central repository, as documented in section . It's also bos@559: usual to publish a read-only copy of the repository over HTTP dongsheng@625: using CGI, as in section . bos@559: Publishing over HTTP bos@559: satisfies the needs of people who don't have push access, and bos@559: those who want to use web browsers to browse the repository's bos@559: history. bos@559: bos@559: bos@559: bos@559: Working with multiple branches bos@559: bos@559: Projects of any significant size naturally tend to make bos@559: progress on several fronts simultaneously. In the case of bos@559: software, it's common for a project to go through periodic bos@559: official releases. A release might then go into bos@559: maintenance mode for a while after its first bos@559: publication; maintenance releases tend to contain only bug bos@559: fixes, not new features. In parallel with these maintenance bos@559: releases, one or more future releases may be under bos@559: development. People normally use the word bos@559: branch to refer to one of these many slightly bos@559: different directions in which development is bos@559: proceeding. bos@559: bos@559: Mercurial is particularly well suited to managing a number bos@559: of simultaneous, but not identical, branches. Each bos@559: development direction can live in its own bos@559: central repository, and you can merge changes from one to bos@559: another as the need arises. Because repositories are bos@559: independent of each other, unstable changes in a development bos@559: branch will never affect a stable branch unless someone bos@559: explicitly merges those changes in. bos@559: bos@559: Here's an example of how this can work in practice. Let's bos@559: say you have one main branch on a central bos@567: server. bos@567: bos@567: &interaction.branching.init; bos@567: bos@567: People clone it, make changes locally, test them, and push bos@567: them back. bos@559: bos@559: Once the main branch reaches a release milestone, you can bos@559: use the hg tag command to bos@567: give a permanent name to the milestone revision. bos@567: bos@567: &interaction.branching.tag; bos@567: bos@567: Let's say some ongoing bos@567: development occurs on the main branch. bos@567: bos@567: &interaction.branching.main; bos@567: bos@567: Using the tag that was recorded at the milestone, people bos@567: who clone that repository at any time in the future can use bos@567: hg update to get a copy of bos@567: the working directory exactly as it was when that tagged bos@567: revision was committed. bos@567: bos@567: &interaction.branching.update; bos@559: bos@559: In addition, immediately after the main branch is tagged, bos@559: someone can then clone the main branch on the server to a new bos@567: stable branch, also on the server. bos@567: bos@567: &interaction.branching.clone; bos@559: bos@559: Someone who needs to make a change to the stable branch bos@559: can then clone that repository, make bos@567: their changes, commit, and push their changes back there. bos@567: bos@567: &interaction.branching.stable; bos@567: bos@567: Because Mercurial repositories are independent, and bos@567: Mercurial doesn't move changes around automatically, the bos@567: stable and main branches are isolated bos@567: from each other. The changes that you made on the main branch bos@567: don't leak to the stable branch, and vice bos@567: versa. bos@559: bos@559: You'll often want all of your bugfixes on the stable bos@559: branch to show up on the main branch, too. Rather than bos@559: rewrite a bugfix on the main branch, you can simply pull and bos@559: merge changes from the stable to the main branch, and bos@567: Mercurial will bring those bugfixes in for you. bos@567: bos@567: &interaction.branching.merge; bos@567: bos@567: The main branch will still contain changes that are not on bos@567: the stable branch, but it will also contain all of the bos@567: bugfixes from the stable branch. The stable branch remains bos@567: unaffected by these changes. bos@559: bos@559: bos@559: bos@559: Feature branches bos@559: bos@559: For larger projects, an effective way to manage change is bos@559: to break up a team into smaller groups. Each group has a bos@559: shared branch of its own, cloned from a single bos@559: master branch used by the entire project. bos@559: People working on an individual branch are typically quite bos@559: isolated from developments on other branches. bos@559: dongsheng@625: dongsheng@640: dongsheng@640: dongsheng@640: dongsheng@640: XXX add text dongsheng@640: Feature dongsheng@640: branches dongsheng@640: bos@559: bos@559: bos@559: When a particular feature is deemed to be in suitable bos@559: shape, someone on that feature team pulls and merges from the bos@559: master branch into the feature branch, then pushes back up to bos@559: the master branch. bos@559: bos@559: bos@559: bos@559: The release train bos@559: bos@559: Some projects are organised on a train bos@559: basis: a release is scheduled to happen every few months, and bos@559: whatever features are ready when the train is bos@559: ready to leave are allowed in. bos@559: bos@559: This model resembles working with feature branches. The bos@559: difference is that when a feature branch misses a train, bos@559: someone on the feature team pulls and merges the changes that bos@559: went out on that train release into the feature branch, and bos@559: the team continues its work on top of that release so that bos@559: their feature can make the next release. bos@559: bos@559: bos@559: bos@559: The Linux kernel model bos@559: bos@559: The development of the Linux kernel has a shallow bos@559: hierarchical structure, surrounded by a cloud of apparent bos@559: chaos. Because most Linux developers use bos@559: git, a distributed revision control tool bos@559: with capabilities similar to Mercurial, it's useful to bos@559: describe the way work flows in that environment; if you like bos@559: the ideas, the approach translates well across tools. bos@559: bos@559: At the center of the community sits Linus Torvalds, the bos@559: creator of Linux. He publishes a single source repository bos@559: that is considered the authoritative current bos@559: tree by the entire developer community. Anyone can clone bos@559: Linus's tree, but he is very choosy about whose trees he pulls bos@559: from. bos@559: bos@559: Linus has a number of trusted lieutenants. bos@559: As a general rule, he pulls whatever changes they publish, in bos@559: most cases without even reviewing those changes. Some of bos@559: those lieutenants are generally agreed to be bos@559: maintainers, responsible for specific bos@559: subsystems within the kernel. If a random kernel hacker wants bos@559: to make a change to a subsystem that they want to end up in bos@559: Linus's tree, they must find out who the subsystem's bos@559: maintainer is, and ask that maintainer to take their change. bos@559: If the maintainer reviews their changes and agrees to take bos@559: them, they'll pass them along to Linus in due course. bos@559: bos@559: Individual lieutenants have their own approaches to bos@559: reviewing, accepting, and publishing changes; and for deciding bos@559: when to feed them to Linus. In addition, there are several bos@559: well known branches that people use for different purposes. bos@559: For example, a few people maintain stable bos@559: repositories of older versions of the kernel, to which they bos@559: apply critical fixes as needed. Some maintainers publish bos@559: multiple trees: one for experimental changes; one for changes bos@559: that they are about to feed upstream; and so on. Others just bos@559: publish a single tree. bos@559: bos@559: This model has two notable features. The first is that bos@559: it's pull only. You have to ask, convince, or bos@559: beg another developer to take a change from you, because there bos@559: are almost no trees to which more than one person can push, bos@559: and there's no way to push changes into a tree that someone bos@559: else controls. bos@559: bos@559: The second is that it's based on reputation and acclaim. bos@559: If you're an unknown, Linus will probably ignore changes from bos@559: you without even responding. But a subsystem maintainer will bos@559: probably review them, and will likely take them if they pass bos@559: their criteria for suitability. The more good bos@559: changes you contribute to a maintainer, the more likely they bos@559: are to trust your judgment and accept your changes. If you're bos@559: well-known and maintain a long-lived branch for something bos@559: Linus hasn't yet accepted, people with similar interests may bos@559: pull your changes regularly to keep up with your work. bos@559: bos@559: Reputation and acclaim don't necessarily cross subsystem bos@559: or people boundaries. If you're a respected bos@559: but specialised storage hacker, and you try to fix a bos@559: networking bug, that change will receive a level of scrutiny bos@559: from a network maintainer comparable to a change from a bos@559: complete stranger. bos@559: bos@559: To people who come from more orderly project backgrounds, bos@559: the comparatively chaotic Linux kernel development process bos@559: often seems completely insane. It's subject to the whims of bos@559: individuals; people make sweeping changes whenever they deem bos@559: it appropriate; and the pace of development is astounding. bos@559: And yet Linux is a highly successful, well-regarded piece of bos@559: software. bos@559: bos@559: bos@559: bos@559: Pull-only versus shared-push collaboration bos@559: bos@559: A perpetual source of heat in the open source community is bos@559: whether a development model in which people only ever pull bos@559: changes from others is better than one in which bos@559: multiple people can push changes to a shared bos@559: repository. bos@559: bos@559: Typically, the backers of the shared-push model use tools bos@559: that actively enforce this approach. If you're using a bos@559: centralised revision control tool such as Subversion, there's bos@559: no way to make a choice over which model you'll use: the tool bos@559: gives you shared-push, and if you want to do anything else, bos@559: you'll have to roll your own approach on top (such as applying bos@559: a patch by hand). bos@559: bos@559: A good distributed revision control tool, such as bos@559: Mercurial, will support both models. You and your bos@559: collaborators can then structure how you work together based bos@559: on your own needs and preferences, not on what contortions bos@559: your tools force you into. bos@559: bos@559: bos@559: bos@559: Where collaboration meets branch management bos@559: bos@559: Once you and your team set up some shared repositories and bos@559: start propagating changes back and forth between local and bos@559: shared repos, you begin to face a related, but slightly bos@559: different challenge: that of managing the multiple directions bos@559: in which your team may be moving at once. Even though this bos@559: subject is intimately related to how your team collaborates, bos@559: it's dense enough to merit treatment of its own, in chapter dongsheng@625: . bos@559: bos@559: bos@559: bos@559: bos@559: The technical side of sharing bos@559: bos@559: The remainder of this chapter is devoted to the question of bos@559: serving data to your collaborators. bos@559: bos@559: dongsheng@625: bos@559: Informal sharing with <command role="hg-cmd">hg bos@559: serve</command> bos@559: bos@559: Mercurial's hg serve bos@559: command is wonderfully suited to small, tight-knit, and bos@559: fast-paced group environments. It also provides a great way to bos@559: get a feel for using Mercurial commands over a network. bos@559: bos@559: Run hg serve inside a bos@559: repository, and in under a second it will bring up a specialised bos@559: HTTP server; this will accept connections from any client, and bos@559: serve up data for that repository until you terminate it. bos@559: Anyone who knows the URL of the server you just started, and can bos@559: talk to your computer over the network, can then use a web bos@559: browser or Mercurial to read data from that repository. A URL bos@559: for a hg serve instance running bos@559: on a laptop is likely to look something like bos@559: http://my-laptop.local:8000/. bos@559: bos@559: The hg serve command is bos@559: not a general-purpose web server. It can do bos@559: only two things: bos@559: bos@559: Allow people to browse the history of the bos@559: repository it's serving, from their normal web bos@559: browsers. bos@559: bos@559: Speak Mercurial's wire protocol, so that people bos@559: can hg clone or hg pull changes from that bos@559: repository. bos@559: bos@559: In particular, hg serve bos@559: won't allow remote users to modify your bos@559: repository. It's intended for read-only use. bos@559: bos@559: If you're getting started with Mercurial, there's nothing to bos@559: prevent you from using hg serve bos@559: to serve up a repository on your own computer, then use commands bos@559: like hg clone, hg incoming, and so on to talk to that bos@559: server as if the repository was hosted remotely. This can help bos@559: you to quickly get acquainted with using commands on bos@559: network-hosted repositories. bos@559: bos@559: bos@559: A few things to keep in mind bos@559: bos@559: Because it provides unauthenticated read access to all bos@559: clients, you should only use hg bos@559: serve in an environment where you either don't bos@559: care, or have complete control over, who can access your bos@559: network and pull data from your repository. bos@559: bos@559: The hg serve command bos@559: knows nothing about any firewall software you might have bos@559: installed on your system or network. It cannot detect or bos@559: control your firewall software. If other people are unable to bos@559: talk to a running hg serve bos@559: instance, the second thing you should do bos@559: (after you make sure that they're using bos@559: the correct URL) is check your firewall configuration. bos@559: bos@559: By default, hg serve bos@559: listens for incoming connections on port 8000. If another bos@559: process is already listening on the port you want to use, you bos@559: can specify a different port to listen on using the option. bos@559: bos@559: Normally, when hg serve bos@559: starts, it prints no output, which can be a bit unnerving. If bos@559: you'd like to confirm that it is indeed running correctly, and bos@559: find out what URL you should send to your collaborators, start bos@559: it with the bos@559: option. bos@559: bos@559: bos@559: dongsheng@625: bos@559: Using the Secure Shell (ssh) protocol bos@559: bos@559: You can pull and push changes securely over a network bos@559: connection using the Secure Shell (ssh) bos@559: protocol. To use this successfully, you may have to do a little bos@559: bit of configuration on the client or server sides. bos@559: bos@559: If you're not familiar with ssh, it's a network protocol bos@559: that lets you securely communicate with another computer. To bos@559: use it with Mercurial, you'll be setting up one or more user bos@559: accounts on a server so that remote users can log in and execute bos@559: commands. bos@559: bos@559: (If you are familiar with ssh, you'll bos@559: probably find some of the material that follows to be elementary bos@559: in nature.) bos@559: bos@559: bos@559: How to read and write ssh URLs bos@559: bos@559: An ssh URL tends to look like this: bos@559: ssh://bos@hg.serpentine.com:22/hg/hgbook bos@559: bos@559: The ssh:// bos@559: part tells Mercurial to use the ssh protocol. bos@559: bos@559: The bos@ bos@559: component indicates what username to log into the server bos@559: as. You can leave this out if the remote username is the bos@559: same as your local username. bos@559: bos@559: The bos@559: hg.serpentine.com gives bos@559: the hostname of the server to log into. bos@559: bos@559: The :22 identifies the port bos@559: number to connect to the server on. The default port is bos@579: 22, so you only need to specify a colon and port number if bos@579: you're not using port 22. bos@559: bos@559: The remainder of the URL is the local path to bos@559: the repository on the server. bos@559: bos@559: bos@559: There's plenty of scope for confusion with the path bos@559: component of ssh URLs, as there is no standard way for tools bos@559: to interpret it. Some programs behave differently than others bos@559: when dealing with these paths. This isn't an ideal situation, bos@559: but it's unlikely to change. Please read the following bos@559: paragraphs carefully. bos@559: bos@559: Mercurial treats the path to a repository on the server as bos@559: relative to the remote user's home directory. For example, if bos@559: user foo on the server has a home directory bos@559: of /home/foo, then an bos@559: ssh URL that contains a path component of bar really bos@559: refers to the directory /home/foo/bar. bos@559: bos@559: If you want to specify a path relative to another user's bos@559: home directory, you can use a path that starts with a tilde bos@559: character followed by the user's name (let's call them bos@559: otheruser), like this. bos@559: ssh://server/~otheruser/hg/repo bos@559: bos@559: And if you really want to specify an bos@559: absolute path on the server, begin the bos@559: path component with two slashes, as in this example. bos@559: ssh://server//absolute/path bos@559: bos@559: bos@559: bos@559: Finding an ssh client for your system bos@559: bos@559: Almost every Unix-like system comes with OpenSSH bos@559: preinstalled. If you're using such a system, run bos@559: which ssh to find out if the bos@559: ssh command is installed (it's usually in bos@559: /usr/bin). In the bos@559: unlikely event that it isn't present, take a look at your bos@559: system documentation to figure out how to install it. bos@559: bos@559: On Windows, you'll first need to download a suitable ssh bos@559: client. There are two alternatives. bos@559: bos@559: Simon Tatham's excellent PuTTY package bos@559: web:putty provides a complete suite bos@559: of ssh client commands. bos@559: bos@559: If you have a high tolerance for pain, you can bos@559: use the Cygwin port of OpenSSH. bos@559: bos@580: In either case, you'll need to edit your hg.ini file to bos@559: tell Mercurial where to find the actual client command. For bos@559: example, if you're using PuTTY, you'll need to use the bos@559: plink command as a command-line ssh bos@559: client. bos@579: [ui] bos@579: ssh = C:/path/to/plink.exe -ssh -i "C:/path/to/my/private/key" bos@559: bos@559: bos@559: The path to plink shouldn't contain bos@559: any whitespace characters, or Mercurial may not be able to bos@559: run it correctly (so putting it in C:\Program Files is probably bos@559: not a good idea). bos@559: bos@559: bos@559: bos@559: bos@559: Generating a key pair bos@559: bos@559: To avoid the need to repetitively type a password every bos@559: time you need to use your ssh client, I recommend generating a bos@559: key pair. On a Unix-like system, the bos@559: ssh-keygen command will do the trick. On bos@559: Windows, if you're using PuTTY, the bos@559: puttygen command is what you'll bos@559: need. bos@559: bos@559: When you generate a key pair, it's usually bos@559: highly advisable to protect it with a bos@559: passphrase. (The only time that you might not want to do this bos@559: is when you're using the ssh protocol for automated tasks on a bos@559: secure network.) bos@559: bos@559: Simply generating a key pair isn't enough, however. bos@559: You'll need to add the public key to the set of authorised bos@559: keys for whatever user you're logging in remotely as. For bos@559: servers using OpenSSH (the vast majority), this will mean bos@559: adding the public key to a list in a file called authorized_keys in their .ssh bos@559: directory. bos@559: bos@559: On a Unix-like system, your public key will have a bos@559: .pub extension. If you're using bos@559: puttygen on Windows, you can save the bos@559: public key to a file of your choosing, or paste it from the bos@559: window it's displayed in straight into the authorized_keys file. bos@559: bos@559: bos@559: bos@559: Using an authentication agent bos@559: bos@559: An authentication agent is a daemon that stores bos@559: passphrases in memory (so it will forget passphrases if you bos@559: log out and log back in again). An ssh client will notice if bos@559: it's running, and query it for a passphrase. If there's no bos@559: authentication agent running, or the agent doesn't store the bos@559: necessary passphrase, you'll have to type your passphrase bos@559: every time Mercurial tries to communicate with a server on bos@559: your behalf (e.g. whenever you pull or push changes). bos@559: bos@559: The downside of storing passphrases in an agent is that bos@559: it's possible for a well-prepared attacker to recover the bos@559: plain text of your passphrases, in some cases even if your bos@559: system has been power-cycled. You should make your own bos@559: judgment as to whether this is an acceptable risk. It bos@559: certainly saves a lot of repeated typing. bos@559: bos@559: On Unix-like systems, the agent is called bos@559: ssh-agent, and it's often run automatically bos@559: for you when you log in. You'll need to use the bos@559: ssh-add command to add passphrases to the bos@559: agent's store. On Windows, if you're using PuTTY, the bos@559: pageant command acts as the agent. It adds bos@559: an icon to your system tray that will let you manage stored bos@559: passphrases. bos@559: bos@559: bos@559: bos@559: Configuring the server side properly bos@559: bos@559: Because ssh can be fiddly to set up if you're new to it, bos@559: there's a variety of things that can go wrong. Add Mercurial bos@559: on top, and there's plenty more scope for head-scratching. bos@559: Most of these potential problems occur on the server side, not bos@559: the client side. The good news is that once you've gotten a bos@559: configuration working, it will usually continue to work bos@559: indefinitely. bos@559: bos@559: Before you try using Mercurial to talk to an ssh server, bos@559: it's best to make sure that you can use the normal bos@559: ssh or putty command to bos@559: talk to the server first. If you run into problems with using bos@559: these commands directly, Mercurial surely won't work. Worse, bos@559: it will obscure the underlying problem. Any time you want to bos@559: debug ssh-related Mercurial problems, you should drop back to bos@559: making sure that plain ssh client commands work first, bos@559: before you worry about whether there's a bos@559: problem with Mercurial. bos@559: bos@559: The first thing to be sure of on the server side is that bos@559: you can actually log in from another machine at all. If you bos@559: can't use ssh or putty bos@559: to log in, the error message you get may give you a few hints bos@559: as to what's wrong. The most common problems are as bos@559: follows. bos@559: bos@559: If you get a connection refused bos@559: error, either there isn't an SSH daemon running on the bos@559: server at all, or it's inaccessible due to firewall bos@559: configuration. bos@559: bos@559: If you get a no route to host bos@559: error, you either have an incorrect address for the server bos@559: or a seriously locked down firewall that won't admit its bos@559: existence at all. bos@559: bos@559: If you get a permission denied bos@559: error, you may have mistyped the username on the server, bos@559: or you could have mistyped your key's passphrase or the bos@559: remote user's password. bos@559: bos@559: In summary, if you're having trouble talking to the bos@559: server's ssh daemon, first make sure that one is running at bos@559: all. On many systems it will be installed, but disabled, by bos@559: default. Once you're done with this step, you should then bos@559: check that the server's firewall is configured to allow bos@559: incoming connections on the port the ssh daemon is listening bos@559: on (usually 22). Don't worry about more exotic possibilities bos@559: for misconfiguration until you've checked these two bos@559: first. bos@559: bos@559: If you're using an authentication agent on the client side bos@559: to store passphrases for your keys, you ought to be able to bos@559: log into the server without being prompted for a passphrase or bos@559: a password. If you're prompted for a passphrase, there are a bos@559: few possible culprits. bos@559: bos@559: You might have forgotten to use bos@559: ssh-add or pageant bos@559: to store the passphrase. bos@559: bos@559: You might have stored the passphrase for the bos@559: wrong key. bos@559: bos@559: If you're being prompted for the remote user's password, bos@559: there are another few possible problems to check. bos@559: bos@559: Either the user's home directory or their bos@559: .ssh bos@559: directory might have excessively liberal permissions. As bos@559: a result, the ssh daemon will not trust or read their bos@559: authorized_keys file. bos@559: For example, a group-writable home or .ssh bos@559: directory will often cause this symptom. bos@559: bos@559: The user's authorized_keys file may have bos@559: a problem. If anyone other than the user owns or can write bos@559: to that file, the ssh daemon will not trust or read bos@559: it. bos@559: bos@559: bos@559: In the ideal world, you should be able to run the bos@559: following command successfully, and it should print exactly bos@559: one line of output, the current date and time. bos@559: ssh myserver date bos@559: bos@559: If, on your server, you have login scripts that print bos@559: banners or other junk even when running non-interactive bos@559: commands like this, you should fix them before you continue, bos@559: so that they only print output if they're run interactively. bos@559: Otherwise these banners will at least clutter up Mercurial's bos@559: output. Worse, they could potentially cause problems with bos@559: running Mercurial commands remotely. Mercurial makes tries to bos@559: detect and ignore banners in non-interactive bos@559: ssh sessions, but it is not foolproof. (If bos@559: you're editing your login scripts on your server, the usual bos@559: way to see if a login script is running in an interactive bos@559: shell is to check the return code from the command bos@559: tty -s.) bos@559: bos@559: Once you've verified that plain old ssh is working with bos@559: your server, the next step is to ensure that Mercurial runs on bos@559: the server. The following command should run bos@559: successfully: bos@580: bos@559: ssh myserver hg version bos@580: bos@559: If you see an error message instead of normal hg version output, this is usually bos@559: because you haven't installed Mercurial to /usr/bin. Don't worry if this bos@559: is the case; you don't need to do that. But you should check bos@559: for a few possible problems. bos@559: bos@559: Is Mercurial really installed on the server at bos@559: all? I know this sounds trivial, but it's worth bos@559: checking! bos@559: bos@559: Maybe your shell's search path (usually set bos@559: via the PATH environment variable) is bos@559: simply misconfigured. bos@559: bos@559: Perhaps your PATH environment bos@559: variable is only being set to point to the location of the bos@559: hg executable if the login session is bos@559: interactive. This can happen if you're setting the path bos@559: in the wrong shell login script. See your shell's bos@559: documentation for details. bos@559: bos@559: The PYTHONPATH environment bos@559: variable may need to contain the path to the Mercurial bos@559: Python modules. It might not be set at all; it could be bos@559: incorrect; or it may be set only if the login is bos@559: interactive. bos@559: bos@559: bos@559: If you can run hg version bos@559: over an ssh connection, well done! You've got the server and bos@559: client sorted out. You should now be able to use Mercurial to bos@559: access repositories hosted by that username on that server. bos@559: If you run into problems with Mercurial and ssh at this point, bos@559: try using the bos@559: option to get a clearer picture of what's going on. bos@559: bos@559: bos@559: bos@559: Using compression with ssh bos@559: bos@559: Mercurial does not compress data when it uses the ssh bos@559: protocol, because the ssh protocol can transparently compress bos@559: data. However, the default behaviour of ssh clients is bos@559: not to request compression. bos@559: bos@559: Over any network other than a fast LAN (even a wireless bos@559: network), using compression is likely to significantly speed bos@559: up Mercurial's network operations. For example, over a WAN, bos@559: someone measured compression as reducing the amount of time bos@559: required to clone a particularly large repository from 51 bos@559: minutes to 17 minutes. bos@559: bos@559: Both ssh and plink bos@559: accept a option which bos@559: turns on compression. You can easily edit your ~/.hgrc to enable compression for bos@559: all of Mercurial's uses of the ssh protocol. bos@579: [ui] bos@579: ssh = ssh -C bos@559: bos@559: If you use ssh, you can configure it to bos@559: always use compression when talking to your server. To do bos@559: this, edit your .ssh/config file (which may not bos@559: yet exist), as follows. bos@579: Host hg bos@579: Compression yes bos@579: HostName hg.example.com bos@559: This defines an alias, hg. When you bos@559: use it on the ssh command line or in a bos@559: Mercurial ssh-protocol URL, it will cause bos@559: ssh to connect to bos@559: hg.example.com and use compression. This bos@559: gives you both a shorter name to type and compression, each of bos@559: which is a good thing in its own right. bos@559: bos@559: bos@559: dongsheng@625: bos@559: Serving over HTTP using CGI bos@559: bos@559: Depending on how ambitious you are, configuring Mercurial's bos@559: CGI interface can take anything from a few moments to several bos@559: hours. bos@559: bos@559: We'll begin with the simplest of examples, and work our way bos@559: towards a more complex configuration. Even for the most basic bos@559: case, you're almost certainly going to need to read and modify bos@559: your web server's configuration. bos@559: bos@559: bos@559: Configuring a web server is a complex, fiddly, and bos@559: highly system-dependent activity. I can't possibly give you bos@559: instructions that will cover anything like all of the cases bos@559: you will encounter. Please use your discretion and judgment in bos@559: following the sections below. Be prepared to make plenty of bos@559: mistakes, and to spend a lot of time reading your server's bos@559: error logs. bos@559: bos@559: bos@559: bos@559: Web server configuration checklist bos@559: bos@559: Before you continue, do take a few moments to check a few bos@559: aspects of your system's setup. bos@559: bos@559: bos@559: Do you have a web server installed at all? bos@559: Mac OS X ships with Apache, but many other systems may not bos@559: have a web server installed. bos@559: bos@559: If you have a web server installed, is it bos@559: actually running? On most systems, even if one is bos@559: present, it will be disabled by default. bos@559: bos@559: Is your server configured to allow you to run bos@559: CGI programs in the directory where you plan to do so? bos@559: Most servers default to explicitly disabling the ability bos@559: to run CGI programs. bos@559: bos@559: bos@559: If you don't have a web server installed, and don't have bos@559: substantial experience configuring Apache, you should consider bos@559: using the lighttpd web server instead of bos@559: Apache. Apache has a well-deserved reputation for baroque and bos@559: confusing configuration. While lighttpd is bos@559: less capable in some ways than Apache, most of these bos@559: capabilities are not relevant to serving Mercurial bos@559: repositories. And lighttpd is undeniably bos@559: much easier to get started with than bos@559: Apache. bos@559: bos@559: bos@559: bos@559: Basic CGI configuration bos@559: bos@559: On Unix-like systems, it's common for users to have a bos@559: subdirectory named something like public_html in their home bos@559: directory, from which they can serve up web pages. A file bos@559: named foo in this directory will be bos@559: accessible at a URL of the form bos@580: http://www.example.com/username/foo. bos@559: bos@559: To get started, find the hgweb.cgi script that should be bos@559: present in your Mercurial installation. If you can't quickly bos@559: find a local copy on your system, simply download one from the bos@559: master Mercurial repository at http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi. bos@559: bos@559: You'll need to copy this script into your public_html directory, and bos@559: ensure that it's executable. bos@579: cp .../hgweb.cgi ~/public_html bos@579: chmod 755 ~/public_html/hgweb.cgi bos@559: The 755 argument to bos@559: chmod is a little more general than just bos@559: making the script executable: it ensures that the script is bos@559: executable by anyone, and that group and bos@559: other write permissions are bos@559: not set. If you were to leave those bos@559: write permissions enabled, Apache's suexec bos@559: subsystem would likely refuse to execute the script. In fact, bos@559: suexec also insists that the bos@559: directory in which the script resides bos@559: must not be writable by others. bos@559: chmod 755 ~/public_html bos@559: dongsheng@625: bos@559: What could <emphasis>possibly</emphasis> go bos@559: wrong? bos@559: bos@559: Once you've copied the CGI script into place, go into a bos@559: web browser, and try to open the URL http://myhostname/ bos@559: myuser/hgweb.cgi, but brace bos@559: yourself for instant failure. There's a high probability bos@559: that trying to visit this URL will fail, and there are many bos@559: possible reasons for this. In fact, you're likely to bos@559: stumble over almost every one of the possible errors below, bos@559: so please read carefully. The following are all of the bos@559: problems I ran into on a system running Fedora 7, with a bos@559: fresh installation of Apache, and a user account that I bos@559: created specially to perform this exercise. bos@559: bos@559: Your web server may have per-user directories disabled. bos@559: If you're using Apache, search your config file for a bos@559: UserDir directive. If there's none bos@559: present, per-user directories will be disabled. If one bos@559: exists, but its value is disabled, then bos@559: per-user directories will be disabled. Otherwise, the bos@559: string after UserDir gives the name of bos@559: the subdirectory that Apache will look in under your home bos@559: directory, for example public_html. bos@559: bos@559: Your file access permissions may be too restrictive. bos@559: The web server must be able to traverse your home directory bos@559: and directories under your public_html directory, and bos@559: read files under the latter too. Here's a quick recipe to bos@559: help you to make your permissions more appropriate. bos@579: chmod 755 ~ bos@579: find ~/public_html -type d -print0 | xargs -0r chmod 755 bos@579: find ~/public_html -type f -print0 | xargs -0r chmod 644 bos@559: bos@559: The other possibility with permissions is that you might bos@559: get a completely empty window when you try to load the bos@559: script. In this case, it's likely that your access ori@561: permissions are too permissive. Apache's bos@559: suexec subsystem won't execute a script bos@559: that's group- or world-writable, for example. bos@559: bos@559: Your web server may be configured to disallow execution bos@559: of CGI programs in your per-user web directory. Here's bos@559: Apache's default per-user configuration from my Fedora bos@559: system. bos@579: dongsheng@648: bos@579: bos@559: If you find a similar-looking bos@559: Directory group in your Apache bos@559: configuration, the directive to look at inside it is bos@559: Options. Add ExecCGI bos@559: to the end of this list if it's missing, and restart the web bos@559: server. bos@559: bos@559: If you find that Apache serves you the text of the CGI bos@559: script instead of executing it, you may need to either bos@559: uncomment (if already present) or add a directive like bos@559: this. bos@559: AddHandler cgi-script .cgi bos@559: bos@559: The next possibility is that you might be served with a bos@559: colourful Python backtrace claiming that it can't import a bos@559: mercurial-related module. This is bos@559: actually progress! The server is now capable of executing bos@559: your CGI script. This error is only likely to occur if bos@559: you're running a private installation of Mercurial, instead bos@559: of a system-wide version. Remember that the web server runs bos@559: the CGI program without any of the environment variables bos@559: that you take for granted in an interactive session. If bos@559: this error happens to you, edit your copy of hgweb.cgi and follow the bos@559: directions inside it to correctly set your bos@559: PYTHONPATH environment variable. bos@559: bos@559: Finally, you are certain to by bos@559: served with another colourful Python backtrace: this one bos@559: will complain that it can't find /path/to/repository. Edit bos@559: your hgweb.cgi script bos@559: and replace the /path/to/repository string bos@559: with the complete path to the repository you want to serve bos@559: up. bos@559: bos@559: At this point, when you try to reload the page, you bos@559: should be presented with a nice HTML view of your bos@559: repository's history. Whew! bos@559: bos@559: bos@559: bos@559: Configuring lighttpd bos@559: bos@559: To be exhaustive in my experiments, I tried configuring bos@559: the increasingly popular lighttpd web bos@559: server to serve the same repository as I described with bos@559: Apache above. I had already overcome all of the problems I bos@559: outlined with Apache, many of which are not server-specific. bos@559: As a result, I was fairly sure that my file and directory bos@559: permissions were good, and that my hgweb.cgi script was properly bos@559: edited. bos@559: bos@559: Once I had Apache running, getting bos@559: lighttpd to serve the repository was a bos@559: snap (in other words, even if you're trying to use bos@559: lighttpd, you should read the Apache bos@559: section). I first had to edit the bos@559: mod_access section of its config file to bos@559: enable mod_cgi and bos@559: mod_userdir, both of which were disabled bos@559: by default on my system. I then added a few lines to the bos@559: end of the config file, to configure these modules. bos@580: userdir.path = "public_html" bos@580: cgi.assign = (".cgi" => "" ) bos@559: With this done, lighttpd ran bos@559: immediately for me. If I had configured bos@559: lighttpd before Apache, I'd almost bos@559: certainly have run into many of the same system-level bos@559: configuration problems as I did with Apache. However, I bos@559: found lighttpd to be noticeably easier to bos@559: configure than Apache, even though I've used Apache for over bos@559: a decade, and this was my first exposure to bos@559: lighttpd. bos@559: bos@559: bos@559: bos@559: bos@559: Sharing multiple repositories with one CGI script bos@559: bos@559: The hgweb.cgi script bos@559: only lets you publish a single repository, which is an bos@559: annoying restriction. If you want to publish more than one bos@559: without wracking yourself with multiple copies of the same bos@559: script, each with different names, a better choice is to use bos@559: the hgwebdir.cgi bos@559: script. bos@559: bos@559: The procedure to configure hgwebdir.cgi is only a little more bos@559: involved than for hgweb.cgi. First, you must obtain bos@559: a copy of the script. If you don't have one handy, you can bos@559: download a copy from the master Mercurial repository at http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi. bos@559: bos@559: You'll need to copy this script into your public_html directory, and bos@559: ensure that it's executable. bos@580: cp .../hgwebdir.cgi ~/public_html bos@580: chmod 755 ~/public_html ~/public_html/hgwebdir.cgi bos@559: With basic configuration out of the way, try to visit bos@559: http://myhostname/ bos@559: myuser/hgwebdir.cgi in your browser. It should bos@559: display an empty list of repositories. If you get a blank bos@559: window or error message, try walking through the list of bos@559: potential problems in section . bos@559: bos@559: The hgwebdir.cgi bos@559: script relies on an external configuration file. By default, bos@559: it searches for a file named hgweb.config in the same directory bos@559: as itself. You'll need to create this file, and make it bos@559: world-readable. The format of the file is similar to a bos@559: Windows ini file, as understood by Python's bos@559: ConfigParser bos@559: web:configparser module. bos@559: bos@559: The easiest way to configure hgwebdir.cgi is with a section bos@559: named collections. This will automatically bos@559: publish every repository under the bos@559: directories you name. The section should look like bos@559: this: bos@580: [collections] bos@580: /my/root = /my/root bos@559: Mercurial interprets this by looking at the directory name bos@559: on the right hand side of the bos@559: = sign; finding repositories bos@559: in that directory hierarchy; and using the text on the bos@559: left to strip off matching text from the bos@559: names it will actually list in the web interface. The bos@559: remaining component of a path after this stripping has bos@559: occurred is called a virtual path. bos@559: bos@559: Given the example above, if we have a repository whose bos@559: local path is /my/root/this/repo, the CGI bos@559: script will strip the leading /my/root from the name, and bos@559: publish the repository with a virtual path of this/repo. If the base URL for bos@559: our CGI script is http://myhostname/ bos@559: myuser/hgwebdir.cgi, the complete URL for that bos@559: repository will be http://myhostname/ bos@559: myuser/hgwebdir.cgi/this/repo. bos@559: bos@559: If we replace /my/root on the left hand side bos@559: of this example with /my, then hgwebdir.cgi will only strip off bos@559: /my from the repository bos@559: name, and will give us a virtual path of root/this/repo instead of bos@559: this/repo. bos@559: bos@559: The hgwebdir.cgi bos@559: script will recursively search each directory listed in the bos@559: collections section of its configuration bos@559: file, but it will not recurse into the bos@559: repositories it finds. bos@559: bos@559: The collections mechanism makes it easy bos@559: to publish many repositories in a fire and bos@559: forget manner. You only need to set up the CGI bos@559: script and configuration file one time. Afterwards, you can bos@559: publish or unpublish a repository at any time by simply moving bos@559: it into, or out of, the directory hierarchy in which you've bos@559: configured hgwebdir.cgi to bos@559: look. bos@559: bos@559: bos@559: Explicitly specifying which repositories to bos@559: publish bos@559: bos@559: In addition to the collections bos@559: mechanism, the hgwebdir.cgi script allows you bos@559: to publish a specific list of repositories. To do so, bos@559: create a paths section, with contents of bos@559: the following form. bos@580: [paths] bos@580: repo1 = /my/path/to/some/repo bos@580: repo2 = /some/path/to/another bos@559: In this case, the virtual path (the component that will bos@559: appear in a URL) is on the left hand side of each bos@559: definition, while the path to the repository is on the bos@559: right. Notice that there does not need to be any bos@559: relationship between the virtual path you choose and the bos@559: location of a repository in your filesystem. bos@559: bos@559: If you wish, you can use both the bos@559: collections and paths bos@559: mechanisms simultaneously in a single configuration bos@559: file. bos@559: bos@559: bos@559: If multiple repositories have the same virtual path, bos@559: hgwebdir.cgi will not bos@559: report an error. Instead, it will behave bos@559: unpredictably. bos@559: bos@559: bos@559: bos@559: bos@559: bos@559: Downloading source archives bos@559: bos@559: Mercurial's web interface lets users download an archive bos@559: of any revision. This archive will contain a snapshot of the bos@559: working directory as of that revision, but it will not contain bos@559: a copy of the repository data. bos@559: bos@559: By default, this feature is not enabled. To enable it, bos@559: you'll need to add an allow_archive item to the bos@559: web section of your ~/.hgrc. bos@559: bos@559: bos@559: bos@559: Web configuration options bos@559: bos@559: Mercurial's web interfaces (the hg bos@559: serve command, and the hgweb.cgi and hgwebdir.cgi scripts) have a bos@559: number of configuration options that you can set. These bos@559: belong in a section named web. bos@559: bos@559: allow_archive: Determines bos@559: which (if any) archive download mechanisms Mercurial bos@559: supports. If you enable this feature, users of the web bos@559: interface will be able to download an archive of whatever bos@559: revision of a repository they are viewing. To enable the bos@559: archive feature, this item must take the form of a bos@559: sequence of words drawn from the list below. bos@559: bos@559: bz2: A bos@559: tar archive, compressed using bos@559: bzip2 compression. This has the bos@559: best compression ratio, but uses the most CPU time on bos@559: the server. bos@559: bos@559: gz: A bos@559: tar archive, compressed using bos@559: gzip compression. bos@559: bos@559: zip: A bos@559: zip archive, compressed using LZW bos@559: compression. This format has the worst compression bos@559: ratio, but is widely used in the Windows world. bos@559: bos@559: bos@559: If you provide an empty list, or don't have an bos@559: allow_archive entry at bos@559: all, this feature will be disabled. Here is an example of bos@559: how to enable all three supported formats. bos@580: [web] bos@580: allow_archive = bz2 gz zip bos@559: bos@559: allowpull: bos@559: Boolean. Determines whether the web interface allows bos@559: remote users to hg pull bos@559: and hg clone this bos@559: repository over HTTP. If set to no or bos@559: false, only the bos@559: human-oriented portion of the web interface bos@559: is available. bos@559: bos@559: contact: bos@559: String. A free-form (but preferably brief) string bos@559: identifying the person or group in charge of the bos@559: repository. This often contains the name and email bos@559: address of a person or mailing list. It often makes sense bos@559: to place this entry in a repository's own .hg/hgrc file, but it can make bos@580: sense to use in a global ~/.hgrc if every repository bos@580: has a single maintainer. bos@559: bos@559: maxchanges: bos@559: Integer. The default maximum number of changesets to bos@559: display in a single page of output. bos@559: bos@559: maxfiles: bos@559: Integer. The default maximum number of modified files to bos@559: display in a single page of output. bos@559: bos@559: stripes: bos@559: Integer. If the web interface displays alternating bos@559: stripes to make it easier to visually align bos@559: rows when you are looking at a table, this number controls bos@559: the number of rows in each stripe. bos@559: bos@559: style: bos@559: Controls the template Mercurial uses to display the web bos@559: interface. Mercurial ships with two web templates, named bos@559: default and gitweb bos@559: (the latter is much more visually attractive). You can bos@559: also specify a custom template of your own; see chapter dongsheng@625: for details. bos@559: Here, you can see how to enable the bos@559: gitweb style. bos@580: [web] bos@580: style = gitweb bos@559: bos@559: templates: bos@559: Path. The directory in which to search for template bos@559: files. By default, Mercurial searches in the directory in bos@559: which it was installed. bos@559: bos@559: If you are using hgwebdir.cgi, you can place a few bos@559: configuration items in a web bos@559: section of the hgweb.config file instead of a bos@580: ~/.hgrc file, for bos@559: convenience. These items are motd and style. bos@559: bos@559: bos@559: Options specific to an individual repository bos@559: bos@559: A few web configuration bos@559: items ought to be placed in a repository's local .hg/hgrc, rather than a user's bos@580: or global ~/.hgrc. bos@559: bos@559: description: String. A bos@559: free-form (but preferably brief) string that describes bos@559: the contents or purpose of the repository. bos@559: bos@559: name: bos@559: String. The name to use for the repository in the web bos@559: interface. This overrides the default name, which is bos@559: the last component of the repository's path. bos@559: bos@559: bos@559: bos@559: bos@559: Options specific to the <command role="hg-cmd">hg bos@559: serve</command> command bos@559: bos@559: Some of the items in the web section of a ~/.hgrc file are only for use bos@559: with the hg serve bos@559: command. bos@559: bos@559: accesslog: bos@559: Path. The name of a file into which to write an access bos@559: log. By default, the hg bos@559: serve command writes this information to bos@559: standard output, not to a file. Log entries are written bos@559: in the standard combined file format used bos@559: by almost all web servers. bos@559: bos@559: address: bos@559: String. The local address on which the server should bos@559: listen for incoming connections. By default, the server bos@559: listens on all addresses. bos@559: bos@559: errorlog: bos@559: Path. The name of a file into which to write an error bos@559: log. By default, the hg bos@559: serve command writes this information to bos@559: standard error, not to a file. bos@559: bos@559: ipv6: bos@559: Boolean. Whether to use the IPv6 protocol. By default, bos@559: IPv6 is not used. bos@559: bos@559: port: bos@559: Integer. The TCP port number on which the server should bos@559: listen. The default port number used is 8000. bos@559: bos@559: bos@559: bos@559: bos@580: Choosing the right <filename bos@580: role="special">~/.hgrc</filename> file to add <literal bos@559: role="rc-web">web</literal> items to bos@559: bos@559: It is important to remember that a web server like bos@559: Apache or lighttpd will run under a user bos@559: ID that is different to yours. CGI scripts run by your bos@559: server, such as hgweb.cgi, will usually also run bos@559: under that user ID. bos@559: bos@559: If you add web items to bos@580: your own personal ~/.hgrc file, CGI scripts won't read that bos@580: ~/.hgrc file. Those bos@559: settings will thus only affect the behaviour of the hg serve command when you run it. bos@559: To cause CGI scripts to see your settings, either create a bos@580: ~/.hgrc file in the bos@559: home directory of the user ID that runs your web server, or bos@559: add those settings to a system-wide ~/.hgrc file. bos@559: bos@559: bos@559: bos@559: bos@559: bos@559: bos@559: bos@559: