Working with Multiple Repositories
In the last tutorial, we covered handling multiple repositories at a conceptual level. In this tutorial, we're going to dive in and start doing this from a practical standpoint in Mercurial.
We're going to cover three basic things here. First, how to clone a repository. Second, how to push changes from one repository to another. Third, how to pull changes from one repository into another.
Our starting point is this:
We have our repository (technically in the .hg folder in our working copy) along with our working copy. We'll extend it from there.
There are two ways that you can clone an existing repository. One is to do a local file system clone, and the second is to do a clone across the network (which still allows you to put the second copy on the same machine as the first).
Local File System Clones
A local file system clone of a repository is the simplest form of cloning that you can do. It's also the least useful. We'll start here anyway, and then proceed to more realistic and better scenarios.
To do a file system clone, right-click on your repository and choose TortoiseHg > Clone…. This brings up the Clone dialog:
Use the Browse button after Destination to find the place you want to create your clone. Once you've got the new location, hit Clone, and like magic, you'll have your new cloned repository created! You can now check into either repository and push and pull changes between them. (More on pushing and pulling later.)
After the clone, we've now got two repositories, each with their own working copy:
These are probably both on the same computer, and at an initial pass, they may look like just two copies of the same directory. Once you open them up, though, you can see that both of them have a .hg folder, so it's easy to tell they're both under version control, and each have their own repository.
A file system clone like this is the simplest way to clone a repository, but it requires you to have a need to have two repositories of the same project on the same computer. That's usually not the case. We're now going to branch out to more sophisticated setups. It probably makes sense to delete the clone we just made (but that's not a requirement — you could leave it hanging around if you really want).
(General Clones? That's a strange title. I should have called it Jango Fett.)
You can use similar steps to create a clone of something that exists anywhere, not just on your file system. To do this, though, you'll need to be able to access the repository from your current location. The easiest way to do this is to basically set up a web server to host your repository.
But don't let "web server" panic you. What we'll do is ridiculously light weight, and it's a part of Mercurial itself. So relax. You don't need to go install Apache or WebLogic or any of that crap. (Though if you've already got one of those, I suspect you could make this work through them, if you were really adventurous and masochistic.)
To start up the built-in web server, right-click in your repository and choose TortoiseHg > Web Server. This will bring up the Web Server window:
You've got your repository hosted in a web server!
If you've already got something running on the default port of 8000, you can choose another port. Usually, you should try to choose a port number higher than 8000, because the lower ports are usually used for common/popular things and you could conflict with them.
You could run multiple servers for multiple repositories on different ports, but the better choice if you've got multiple repositories is to just add them to the list in the bottom part of the window. (You'd have to stop the server temporarily to add them.)
Here's a cool trick. Click on this link: http://localhost:8000
If your server is running (and you didn't change the port) that should bring up your repository in a web interface! How cool is that?!
OK, now that the repository is up and running, you can go clone it. This follows the same general process as before. Create a new folder where you want the new repository to live.
Right-click on or in the folder and choose TortoiseHg > Clone…. Now, in the source field, type http://localhost:8000 and hit Clone.
You've now got your clone!
What I just described is usually enough for a small team of people. If you've got a server that is shared among the team members, you can put the "central" repository there and host it. Each team member can clone from there like we've just described. We have not accounted for permissions, so right now, anyone who has access to the repository can commit to it. There are ways you can configure this, but for these more complicated scenarios, I'll push you in the direction of BitBucket, which we'll talk about next tutorial.
At any rate, we've done everything we need with cloning for now. Let's move on to pushing and pulling.
At this point, you should have at least two repositories, one of which is hosted in the web server.
Let's go back to the clone you made (Working Copy #2 in the above diagram) and make some changes. It doesn't really matter what changes you make, so just do anything. I'm going to edit Design.txt once again.
The change now lives in my working copy only. It hasn't been committed to any repository at all yet, but that's the next step.
Commit to this local repository like we've done with commits in the past. (Right-click, Hg Commit…, add a comment, and commit.)
The change now lives in our local repository, but that's it. We still need to push the change back to the central repository that is being hosted in our web server.
Moving changes from a repository out to another is called "pushing the changes", or "doing a push". That's what we're going to do next, to get our change into the other repository.
To do this, we'll use the Mercurial Workbench, which I first mentioned in passing a few tutorials ago. You can open this from the Start menu, but it may be easier to just right-click and select Hg Workbench.
You'll probably have only one item on the left side, but as you add more projects, more will appear there.
In the top right, you'll see the history of all of your changes in reverse order (most recent changes on top).
We're ready to push our changes to the central repository from here. But first, I need to draw your attention to two sets of icons at the top of the window. The first is the Task Toolbar:
The second is the Sync Toolbar:
If you don't see either of both of these, you can add them from the View > Workbench Toolbars menu item.
The Sync Toolbar has four icons that we'll be using shortly. The second is the Pull icon. The fourth is the Push icon. The first is sort of a "test pull" (hence the ghosted image). This tells you what would get pulled without actually doing the pull. The third is a "test push" icon, which similarly tells you what would be pushed without actually doing the push.
It's at this point that I'd like to say "Hit the Push icon and you're done!" but alas, that's not quite the case. (Go ahead and push it and you'll see why.)
Things aren't configured correctly yet. We need to tell it where we intend to push to. Probably 99% of the time, there will be one repository that you want to push to (or pull from). We can configure this once up front and be done with it. But you'll also be able to configure multiple repositories so you can push and pull from anywhere.
To configure the Hg Workbench for pushing and pulling, we have to go back to that first toolbar I showed you: the Task Toolbar. There are five icons on this toolbar. These buttons essentially change the mode that the Hg Workbench is running in. By clicking on these buttons, the lower right portion of the screen will change to contain a different widget.
The two that you'll use the most are the ones on each end. On the left end is the Revision Details task, which is probably already selected. (It's the default.)
On the other end is the Syncronize task, represented by two green arrows.
To configure the Hg Workbench to know where you want to push and pull from, push this button to switch over to the Synchronization Task. You'll see the lower right part of the screen rearrange itself to look like this:
We want to add our central repository (in this case, the one we put into the web server) to the list in the bottom center, which is currently empty. To do this, in the bar just above this (it's not labeled) type in the location of the repository (http://localhost:8000) and hit the save button to the left of the bar.
This will allow you to specify an alias for the repository, which is just some text that you can use to identify the repository more quickly. I'm calling mine "Central". (Note that you could add all of your team mates' repositories and be able to push to them individually as well.)
Now that Hg Workbench knows where we want to push to, in the future, pushing will be a one-step process. (We won't need to repeat what we just did very often.)
To actually push the changes, you can now hit that Push button on the toolbar at the top (the fourth icon on the Sync Toolbar).
It will ask you to confirm where you're pushing to, and off you go! When it's done, you'll see a little green message near the top of the window telling you the push was completed.
At this point, the change has now been pushed to this other central/web hosted repository!
There is one last thing we need to do here. The change was committed to get moved from working copy to the repository, and pushed to go from one repository to another. But now that change is sitting their in the repository, and the working copy is out of date.
To fix this, we'll do and update. The update command takes changes from the repository that a working copy is attached to and moves them from the repository to the working copy.
To update your working copy, simply right-click in your project folder and choose TortoiseHg > Update…. (Not to be confused with TortoiseHg > Update Icons, which refreshes the little overlay icons in the event that they get out of date.)
This will bring up the Update Dialog:
Go ahead and push Update to get the change, which you'll now see in this working copy as well. We've now migrated changes all the way from a different working copy, through two different repositories, and into our original working copy!
Pulling changes is the same thing conceptually as pushing changes (moving a set of changes from one repository to another) but the perspective is different. Pulling changes takes changes from a different repository and pulls them into the one you're currently working from, whereas pushing changes moves them out from the current repository to another one.
Doing a pull operation is almost identical to a push operation. Like with a push operation, you start by opening up TortoiseHg Workbench. Go back to the top to the SyncToolbar.png:
This time, you'll use the second icon, which is the Pull icon. Once you hit it, Mercurial will do a pull, grabbing changes from the other repository and bring them into your local repository.
Like before, any changes that were brought in only exist in the repository, not the working copy, so you need to do an update to move those changes to your local copy.
Putting it Together
We've introduced a lot of new concepts here, and in an attempt to help solidify it in your mind, I want to present things again from a slightly different perspective.
The usual way things will be set up if you're working with more than one repository is that you'll have a repository that is deemed the central repository. (Remember, Mercurial doesn't care about labels like this; to Mercurial, no repository has greater importance than another, but it almost always makes sense to uses labels like this for the sake of the humans using the system.)
Everybody on your team (it may be a team of one) will clone this central repository, giving them each a local repository, and a working copy. Everybody gets a local repository, and everybody gets a working copy. (Nobody should be using the central repository as their working copy.)
The central repository provides a central area for all people to share, but it also provides a way for you to create off-site or off-box backups (or neither) depending on where the central repository is located. If your hard drive fails, you can always just clone the central repository again. You may lose any changes you made to your local repository, but that's it.
You will occasionally check to see if anyone else has added changes to the central repository by doing a pull from the central repository to your own.
If changes came in from the central repository, you'll also do an update to get the changes into your working copy.
When you've got changes of your own that you want to save, you do a commit. This gets put into your local repository, not the central repository, and not anyone else's repositories. This is one of the biggest advantages of distributed version control: you can commit changes to your repository without inflicting those changes on the rest of the world.
Finally, when you've got everything good and ready, you do a push up into the central repository. At this point, everyone else will do their own pulls to get your changes, just like you did with theirs.
The concepts of pushing and pulling, updating and committing, and cloning are all very important to understanding how Mercurial and distributed version control works. Take whatever time it takes playing around with this to make sure you understand how these topics work.
If you get hung up, please ask for help in the comments or by emailing me. (These tutorials are still perhaps a little rough.)
In the next tutorial, we'll get into how to use BitBucket as the central repository.