views:

233

answers:

2

In short:
How can I use Hg to synchronize repositories between two computers using a flash drive as intermediary?

With more detail:
I often develop code on computers that aren't networked in any way, and I transfer files between these machines using a USB flash drive. Now I would like to develop some software across these machines using Hg repositories on each machine that I can frequently sync-up using the flash drive transfer mechanism.

I'm slightly familiar with Hg, as I use it in the most simple way possible for versioning only my own work on independent machines, but am uncertain as to exactly what I should do to use it to synchronize repositories between two computers using a flash drive as intermediary. Maybe, for example, I need to create a temporary repository on the flash drive (using “clone”) from which I then sync to (using “push” and “pull”), and do this by A→flash, flash→B, B→flash, flash→A? The more specificity in your answer regarding the sequence of actions and commands, the more useful to me.

Finally, how do I get this process started? Do I need to do something so Hg knows these are all part of one code base? For example, each of my current repositories on the different computers was created independently from a time before I started using Hg, and although all the code is similar, independent changes have been made to each, and the repositories know nothing about each other. If what I need to do with this is different than what I need to do for the ongoing case once I have everything unified, spelling this process out for me as well would also help.

In case it's important, these machines can be running any of Windows, Mac, or Linux, and my versions of Mercurial are slightly different on each machine (though the Mercurial versions could be unified if needed).

+4  A: 

What you have described above in terms of using the flash drive as an intermediate storage location should work. My process would be:

initial setup

  1. create repo on computer A (using hg init)
  2. clone the repo from computer A to flash drive

    hg clone C:/path/to/repo/A X:/path/to/flash/drive/repo

  3. clone the repo from flash drive to computer B

    hg clone X:/path/to/flash/drive/repo C:/path/to/repo/B

working process

  1. edit/commit to repo on computer A
  2. push from computer A to flash drive

    hg push X:/path/to/flash/drive/repo

  3. pull from flash drive to computer B

    hg pull X:/path/to/flash/drive/repo

  4. edit/commit repo on computer B

  5. push from computer B to flash drive (same commands as above)
  6. pull from flash drive to computer A (same commands as above)

Finally, how do I get this process started? Do I need to do something so Hg knows these are all part of one code base?

Mercurial knows if two arbitrary repositories have a common ancestor by looking at the SHA1 hash keys of the commits in each repo. In other words, assuming both repos have at least one common hash key in their histories, Mercurial will attempt to merge them. In your specific case, where both repos are initially un-versioned, Mercurial will need some help. The best thing to do would be to get to a place where both repos are identical and then perform your hg init. Mercurial should handle sharing from this point on.

dls
Thank! This is a very useful and clear explanation (so +1). I think I understand everything except for how to "get to a place where both repos are identical". Should I just use some non-Mercurial diff tool for this?
tom10
@tom10 : Initial setup by dls should work or try the step by step approach that I have provided in edited answer.
pyfunc
@tom10: yes, a diff tool would help you do this. If I was performing this task I would use kdiff to perform a directory diff on repoA and repoB and them merge each file into repoA. Afterwards, repoA will be your 'starting point'.
dls
@dls: To make sure I have the basic idea right... your approach basically sets up a permanent repository on the usb flash drive which I then use as an intermediary to update the repos on the computers, right? (By “permanent” here I only mean that the original repo that is cloned to the flash drive is intended to last for more than one sync.) And this is the main practical difference between your method and pyfunc's bundle method, since the bundle does not make any assumptions about the USB flash drive.
tom10
@tom10: the repo on the flash drive is really just used for temporary storage in order to push from computerA to computerB and vice-versa. If you have network access there are many easier ways you can do this (hg serve, create a bitbucket repo, etc..). I would consider one of the computer repos the 'permanent' repo, and if possible, I would back it up on bitbucket or a networked drive when possible. The bundle method pyfunc describes allows more flexibility because you can email bundles or transfer them in other ways.
dls
@dls: OK, but is the following true or false... *for this (i.e. what you outline, not the bundles) to work I need a full repository on the usb drive during the transaction, so either: 1) I use the repo already on the usb drive from a previous session and push to it, or 2) I need to "clone" the full repository onto it for the transaction.* To me, it seems like a simple and clean approach to have a dedicated usb key with a repository that I just update along with repoA and repoB, but I want to make sure that this is the concept before I start.
tom10
@tom10: this is true!
dls
@dls: Great. This all seems very clear to me now and I appreciate your taking the time to explain it, and your original clearly written answer. I think what I'm going to do is just buy a dedicated USB drive and use it as a permanent repository for syncing my various projects. This seems to closely parallel the common way of using Hg, down to the nearly identical commands, but with the USB key used in place of an online repository.
tom10
+2  A: 

When working offline on different machines. It is better to use the bundle command that comes with Mercurial. So echoing what dls wrote but a slight change process.

Initial setup as mentioned by dls. or

  1. Go to your Mercurial repository top directory
  2. Create bundle: hg bundle --base null ../project.hg
  3. Copy the project.hg file to your other computer
  4. Create a directory there
  5. Make it an Mercurial repository : hg init
  6. Incorporate the bundle: hg pull <path/project.hg>
  7. hg update
  8. Check hg log, both the repository will show same base revisions and tip

Workflow using bundle

I use a slightly different workflow. I keep these repositories as distinct repositories. I mention them as repo1 and repo2.

Suppose that the current tip of repo1 is 4f45839f613c.

  1. You make changes and commit them in repo1
  2. Create a bundle of the changes :

Command : This bundle contains all changes since the specified base version.

hg bundle --base 4f45839f613c changes.bundle
  1. Take it to repo2 by copying the bundle.
  2. You can simply pull the bundle to repo2 :

Command :

hg pull changes.bundle

If the bundle contains changes that are already present in repo2, then these will be ignored when pulling. As long as the bundle doesn't grow to large, this allows to use the bundle command with the same --base revision again and again to create bundles including further changes.

About bundles: these are (very well) compressed.

creates a (compressed) backup of the repository

hg bundle --base null backup.bundle

[Edit : Adding some links on this topic]

[Edit: What I think is advantage of using bundle]

Bundles can be created offline, copied or sent via mail. Using push to repo on flash drive, requires it to be connected. Bundles are easier since it does not maintain that the two repo from which you push and pull have to be available at the same time.

Apart from that, bundles can also be of two types : Changesets and Incremental. Changeset bundles are complete standalone bundles. You can also use bundles for backup as a single file.

pyfunc
@pyfunc: what's the advantage of pulling from changes.bundle as opposed to pull from a cloned repo located on the flash drive? You mention that the bundles are very compressed, which is a benefit, but what else?
dls
@dls: See my edited reply. The workflow you have provided is correct and works but I felt that bundle is an easier approach to offline interactions between repo.
pyfunc
I'm not quite sure I get it... to use this approach, each time I sync my repositories, I'd need to know which of my previous commits was the last commit I bundled off computer A to sync with B and visa versa? Also, if I took the bundle off A, and then forget to sync to B, and then later took another bundle off A but only bundled from the commit of my previous bundle onward (since I didn't realize I forgot to pull to B) couldn't things get hopelessly messed up? (btw, +1 because I like this idea, even though I'm confused.)
tom10
@tom10 : Bundles can be created from base. You can keep the base the same for a long time. It is just that this means the certain change-sets that are already in B will be included in the bundle. As I said, this means your bundle will grow in size but when you pull, only changesets that are not included already will get pulled. Good thing is that you could create the bundle offline. Copy it when ever you want and pull when ever you want. I have been using bundles where I mail the bundles to others for them to incorporate. I suggest, play around with this technique and see the ease of it
pyfunc
@pyfunc: One more question for you... if bundles are used to keep the content of these repositories identical, in what sense are they "distinct repositories" when compared to the method that dls describes.
tom10
@tom10: Bundles are a way to create a archive of change sets that can be pulled in other repositories. Both repo are independent and you can bring changes from one repo to another via bundle.
pyfunc
@pyfunc: Many thanks for your interesting answer. I plan to start using bundles right away, and they look to be a very useful option to know about (though I will be using them for a somewhat different problem than the syncing of the repositories... more to send people updates through email/download, as you suggest to be one of their specialty uses).
tom10