[Openslp-devel] mercurial instructions
Brought to you by:
jcalcote
From: John C. <joh...@gm...> - 2012-11-27 17:57:59
|
Ok - now that we've moved over to mercurial, perhaps a little introduction and a few ground rules would be in order: First, mercurial (as you know) is a distributed version control system (DVCS), which basically means one thing - your work area is a snapshot of the entire repository, including all history, branches, tags, etc. Under a traditional non-distributed VCS system like CVS or Subversion, this would be expensive, but a DVCS manages your work area history as a set of diffs from one revision to the next, so it's pretty efficient. If you still have your subversion work area around, you might do a size comparison just for the fun of it. Like subversion, mercurial manages its historical information in a "hidden" sub-directory called .hg. Unlike subversion, there's only one of these .hg directories right under the root of the repo. Many of the features of subversion have corollary functionality in mercurial, such as the "update" command, the "status" command, etc. These functions operate just as you'd expect them to. Some mercurial functionality, however is different and you need to understand these differences to use them properly. For instance, the commit operation exists in mercurial, but it commits a change set to your local copy of the repository. In fact, the update command updates from your local copy of the repository, rather than from the copy on sourceforge.net. This is very nice because you have the opportunity to modify your local history until it's just the way you like it. When you're ready to publish your changes to the world, you use the "push" command to push your local changes up to the master repo. Be careful with push - once you push, you're committed in the same manner you were under subversion commit. Until you push, however, everything in your copy of the repo is fair game for changes you might like to make to it. In reality, there is no concept of a "master" repo in a DVCS. Technically, everyone's copy of a repository is just as valid as anyone else's copy. However, to maintain some semblance of sanity in a project, a particular copy of the repo is usually designated (by general agreement) as the "master" copy. In this case, the master copy is the one hosted by sourceforge.net. When you "clone" a repository, the default push/pull path for your repository is automatically configured to be the location from which you cloned. This makes it simple to push your changes back to the same repo from which you originally cloned - you simply "hg push" and your changes go back to the repo your data originally came from. This origination information is stored in a configuration file within the repo's .hg directory - it's called .hg/hgrc. Cat or Type this file after you clone your repo and you'll see it contains two lines: [paths] default = ssh://jca...@hg.../p/openslp/mercurial You can change the default path for push/pull by simply changing this line of text in the .hg/hgrc file, or you can use a location URL argument to the push/pull commands to override the default path. Having the default path configured in this way makes it easier to work in a manner that's similar (if not the same as) the way we worked under subversion, updating from, and pushing changes to a "master" repo. There's a master configuration file found in the root of your user directory called ~/.hgrc. You can add configuration lines to this file to provide enhanced functionality tailored for your work habits or needs. Here's a copy of my ~/.hgrc file (slightly edited to remove project-specific entries) for your information: # --- User interface --- # [ui] username = John Calcote <joh...@gm...> ssh = "c:\program files (x86)\putty\plink.exe" -ssh -l jcalcote -i "c:\users\jcalcote\keys\id_rsa.ppk" -batch [trusted] users = * groups = * [extensions] hgsubversion = /users/jcalcote/dev/hg/hgsubversion/hgsubversion color = transplant = purge = graphlog = rebase = mq = fetch = graphlog = progress = [color] mode = auto status.modified = magenta bold status.added = green bold status.removed = red bold status.deleted = cyan bold status.unknown = blue bold status.ignored = black bold [extdiff] cmd.meld = meld [merge-tools] meld.args = $base $local $other [tortoisehg] vdiff = meld ui.language = en editor = "C:\Program Files (x86)\notepad++\notepad++.exe" tabwidth = 3 forcerepotab = True Another difference that's important to recognize is that while you're making changes to your copy of the repo, another team member is making changes to his copy also. Conflicts occur when you both try to push your modified repos to the "master". When this happens, the second push causes a branch to be created in the master repo that must be merged back into the main line. It's the second guy's job to merge. In my professional use of mercurial, we use a "gatekeeper" to ensure that branches aren't created in the master repo. Changes are bundled up and pushed to the gatekeeper's mail box. He unbundles these changes, and commits them when he's satisfied they meet all the criteria for a valid commit. We don't have a gatekeeper in our setup, so we have to be more careful in how we work if we want to keep a decent looking master repo. One way to do this is to use a patch queue. In the above .hgrc file, you'll see an entry under the [extensions] section, "mq=". This entry enables mercurial patch queues, which is built into later versions of mercurial, but must be enabled with this configuration statement. Once enabled, you can treat your changes like a stack of patches that can be pushed onto and popped off of your local history - a set of semi-committed changes that can be manipulated more readily with a patch queue than without. hg qnew -m "Some commit message" patch-name.patch hg qpush hg qpop hg qseries (displays the current patch stack) With patches enabled, you can pull the latest code from sf.net and make changes to it over several days or weeks, keeping your changes in a set of patches. When you're ready to push your changes to the master repo, you pop all your patches, pull the latest code down from sf.net and then push your patches back on. This effectively moves the conflicts down to your local repo. You can fix any conflicts that might have been created by changes pushed up to sf.net while you were working. You can also incrementally update your local repo on a daily basis under your patch queue in order to reduce the amount of conflict you have to deal with all at once just before you're ready to push. When a conflict does happen because you and another were unlucky enough to push at the same time (usually within the same 5 minute period), then the last one in will have to merge in the master. This means pulling down an updated copy after the conflict has been created, and merging the branches together, then pushing back up again. I'm making it a rule that the second pusher (the one whose changes didn't make it into the master on the tip of the branch) be the person responsible for the merge in order to keep the conflict from happening multiple times in a row because to pusher's keep trying to do the merge at the same time. All of this is unlikely in our project, but it's worth having a plan for when/if it does. I highly recommend reading (or at least skimming) the mercurial manual, published by the authors of mercurial - Selenic Consulting: http://mercurial.selenic.com/ It's fairly light reading and very helpful. I also highly recommend the use of a graphical tool to manage certain aspects of your repo. TortoiseHG is a wonderful addition to your tool box - it's written in QT and is thus portable to both Windows and Linux. You can install it on linux from apt-get or zypper or whatever platform software installation tool. You can install it on windows by downloading an installer - google it. When you run "thg" from the command line in a working directory, TortoiseHG presents a graphical display of your local repo, including your patch queue and any local commits you may have made. It really helps you get your head around your repo's recent history and the way patches are applied to that history. Regards, John |