Mercurial (Hg)
Distributed Version Control System
Mercurial (Hg)
Overview
Mercurial is a distributed version control system written in Python, designed for efficiency and ease of use. Created by Matt Mackall in 2005, Mercurial emphasizes simplicity, performance, and cross-platform compatibility. While Git has become more popular, Mercurial offers a more consistent and user-friendly command-line interface, making it popular among teams that value simplicity and reliability.
Details
Mercurial follows a distributed architecture similar to Git, where each repository contains the complete project history. However, Mercurial emphasizes consistency and safety, with a more predictable command set and stronger guarantees about repository integrity.
The system uses a simple branching model with named branches and bookmarks (similar to Git branches). Mercurial's approach to branching is more explicit and permanent compared to Git's lightweight branches, which can be both an advantage for clarity and a limitation for certain workflows.
Key features include built-in web interface, excellent cross-platform support, powerful extension system, and strong handling of binary files. Mercurial's Python foundation makes it highly extensible and provides excellent Unicode support.
The tool excels in environments where consistency, simplicity, and reliability are prioritized over the flexibility that Git provides. Mercurial's design philosophy emphasizes doing the right thing by default and making dangerous operations harder to perform accidentally.
Advantages and Disadvantages
Advantages
- Consistent Interface: Predictable and logical command structure
- Cross-platform Excellence: Runs identically on all major platforms
- Safety First: Prevents dangerous operations by default
- Better Binary Handling: Superior performance with large binary files
- Built-in Web Interface: Repository browsing without external tools
- Python Extensibility: Easy to extend and customize
- Unicode Support: Excellent handling of international characters
- Simpler Mental Model: More straightforward than Git for many operations
Disadvantages
- Declining Popularity: Smaller community and ecosystem
- Limited Hosting Options: Fewer cloud hosting services
- Performance with Large Repos: Can be slower than Git for huge repositories
- Branching Limitations: Less flexible branching model
- Fewer Integrations: Limited third-party tool support
- Learning Resources: Fewer tutorials and guides available
- Job Market: Less demand for Mercurial skills
Reference Pages
- Mercurial Official Website
- Mercurial Documentation
- Mercurial Book
- Mercurial Tutorial
- Mercurial Extensions
- TortoiseHg Documentation
Code Examples
Repository Initialization and Basic Operations
# Initialize a new Mercurial repository
hg init myproject
cd myproject
# Clone an existing repository
hg clone https://example.com/repo myproject
# Check repository status
hg status
hg st # Short form
# Add files to tracking
hg add filename.txt
hg add . # Add all untracked files
# Commit changes
hg commit -m "Initial commit"
hg ci -m "Short form commit"
# View commit history
hg log
hg log --graph # Show branching graphically
Working with Files and Changes
# Update working directory to latest revision
hg update
hg up # Short form
# Update to specific revision
hg update -r 123
hg up tip # Update to latest revision
# Show differences
hg diff
hg diff filename.txt
hg diff -r 10:20 # Between revisions
# View file at specific revision
hg cat -r 15 filename.txt
# Remove files
hg remove filename.txt
hg rm filename.txt # Short form
# Rename/move files
hg rename oldname.txt newname.txt
hg mv oldname.txt newname.txt # Short form
# Revert changes
hg revert filename.txt
hg revert --all # Revert all changes
Branching and Merging
# Create a named branch
hg branch feature-branch
hg commit -m "Start feature branch"
# List branches
hg branches
# Switch to different branch
hg update feature-branch
# Merge branches
hg update default # Switch to target branch
hg merge feature-branch
hg commit -m "Merge feature branch"
# Close a branch
hg update feature-branch
hg commit --close-branch -m "Close feature branch"
# Working with bookmarks (lightweight branches)
hg bookmark feature-bookmark
hg bookmarks # List bookmarks
hg update feature-bookmark
Remote Repository Operations
# Add remote repository path
echo "default = https://example.com/repo" >> .hg/hgrc
# Push changes to remote
hg push
hg push -b feature-branch # Push specific branch
# Pull changes from remote
hg pull
hg pull -u # Pull and update working directory
# View remote paths
hg paths
# Clone specific branch
hg clone -b branch-name https://example.com/repo
# Push new branch to remote
hg push -B bookmark-name # Push bookmark
hg push --new-branch # Allow pushing new branch
Advanced Operations
# Interactive history editing (requires histedit extension)
hg histedit
# Shelve changes temporarily
hg shelve
hg shelve --list
hg unshelve
# Patch management (requires mq extension)
hg qinit # Initialize patch queue
hg qnew patch-name # Create new patch
hg qpush # Apply patches
hg qpop # Remove patches
# Bisect to find problematic revision
hg bisect --reset
hg bisect --bad # Mark current revision as bad
hg bisect --good 100 # Mark revision 100 as good
# Mercurial will guide you through the process
# Export patches
hg export -r 10:15 -o patch-%n.diff
# Import patches
hg import patch-file.diff
Repository Information and Analysis
# Show repository summary
hg summary
hg sum # Short form
# Show current revision info
hg identify
hg id # Short form
# Show file history
hg log filename.txt
hg filelog filename.txt
# Show line-by-line authorship
hg annotate filename.txt
hg blame filename.txt # Alternative command
# Find files in repository
hg files
hg files -r 123 # Files at specific revision
# Repository verification
hg verify
# Show repository configuration
hg config
hg showconfig # Alternative command
Working with Tags
# Create a tag
hg tag v1.0.0
hg tag -r 123 v1.0.0 # Tag specific revision
# List tags
hg tags
# Update to tagged revision
hg update v1.0.0
# Remove tag
hg tag --remove v1.0.0
# Create local tag (not shared)
hg tag -l local-tag
Extensions and Configuration
# Enable extensions in .hgrc
[extensions]
histedit =
rebase =
shelve =
mq =
color =
pager =
# Configuration example (.hgrc)
[ui]
username = Your Name <[email protected]>
editor = vim
merge = vimdiff
[web]
push_ssl = true
allow_push = *
[alias]
st = status
ci = commit
l = log --graph
Conflict Resolution
# When conflicts occur during merge
hg status # Shows conflicted files
# View conflict markers in file
cat conflicted-file.txt
# Mark conflicts as resolved
hg resolve --mark conflicted-file.txt
# Use merge tools
hg resolve --tool vimdiff conflicted-file.txt
# List unresolved conflicts
hg resolve --list
# After resolving all conflicts
hg commit -m "Merge conflict resolution"
Web Interface and Sharing
# Start built-in web server
hg serve
hg serve -p 8080 # Specify port
# Serve repository over network
hg serve --address 0.0.0.0 -p 8000
# Clone from web interface
hg clone http://localhost:8000/ local-copy
# Push via HTTP
hg push http://example.com/repo
# Authentication for HTTP
# Add to .hg/hgrc:
[auth]
example.prefix = https://example.com/
example.username = your-username
example.password = your-password
Hook Scripts and Automation
# Example hooks in .hg/hgrc
[hooks]
pre-commit = echo "About to commit..."
post-commit = echo "Committed changeset $HG_NODE"
pre-push = python:myhooks.validate_push
incoming = hg update
# Python hook example (myhooks.py)
def validate_push(ui, repo, **kwargs):
"""Prevent push of changesets with 'WIP' in message"""
for rev in kwargs['pushed_revs']:
ctx = repo[rev]
if 'WIP' in ctx.description():
ui.warn("Cannot push changesets marked as WIP\n")
return True # Abort the push
return False # Allow the push
Performance and Maintenance
# Repository statistics
hg debugstatistics
# Garbage collection (rare need)
hg gc
# Repair repository
hg recover
# Convert from other VCS
hg convert /path/to/svn/repo mercurial-repo
hg convert --source-type git /path/to/git/repo hg-repo
# Archive specific revision
hg archive -r tip ../backup.tar.gz