Mercurial

バージョン管理分散型PythonDevOpshgシンプル操作DVCS

バージョン管理ツール

Mercurial

概要

Mercurial(コマンド名:hg)は、Matt Mackallによって2005年に開発されたオープンソースの分散型バージョン管理システムです。Pythonで実装され、「シンプルで直感的な操作」を設計理念とし、Git と同時期に開発されました。分散型アーキテクチャによる高いパフォーマンスと柔軟性を持ちながら、Gitよりも学習しやすいコマンド体系を提供します。プラットフォーム非依存性とPythonエコシステムとの親和性により、科学計算・研究開発分野で特に支持されており、Pythonベースの拡張機能により高度なカスタマイズが可能です。

詳細

Mercurial 2025年版は、0.3%の小さなマーケットシェアながら、Python開発者や研究機関を中心に根強い支持を獲得しています。GPL v2ライセンスの下でオープンソースとして提供され、安定性と信頼性を重視した開発が継続されています。主要実装言語がPythonであることにより、拡張機能の開発が容易で、科学計算分野でのワークフローにシームレスに統合できます。分散型でありながらGitほど複雑ではない設計により、ブランチ概念が Named Branch と Anonymous Branch(Bookmark)に分かれ、シンプルなワークフローを実現します。

主な特徴

  • Python実装: 拡張性の高いアーキテクチャとPythonエコシステム統合
  • シンプルな操作: 直感的なコマンド体系と学習コストの低さ
  • プラットフォーム独立性: Windows、Linux、macOSでの一貫した動作
  • 効率的なブランチ管理: Named BranchとBookmarkによる柔軟なワークフロー
  • 強力な拡張システム: Pythonによるカスタム機能の実装
  • Web インターフェース: 内蔵Webサーバーによるリポジトリブラウジング

メリット・デメリット

メリット

  • 0.3%の小さなマーケットシェアながらPython開発者に高い支持
  • シンプルなコマンドとPythonベースの実装による拡張性
  • Gitよりも学習しやすい一貫したコマンド体系
  • 科学計算・研究分野でのワークフロー統合実績
  • プラットフォーム独立性による高い互換性
  • 内蔵Webサーバーによる簡単なリポジトリ共有

デメリット

  • 小さなマーケットシェアによる情報・ツールの限定性
  • GitHubやGitLabとの互換性なし(専用ホスティング必要)
  • 新規チームメンバーの学習コストとツール習得
  • モダンなDevOpsエコシステムとの統合がGitに劣る
  • エンタープライズレベルのホスティング選択肢の少なさ
  • コミュニティとエコシステムの縮小傾向

参考ページ

書き方の例

インストールと初期設定

# Mercurialのインストール
# Ubuntu/Debian
sudo apt-get install mercurial

# macOS (Homebrew)
brew install mercurial

# Windows (公式インストーラー使用)
# https://www.mercurial-scm.org/downloads

# バージョン確認
hg version

# グローバル設定
hg config --edit
# または直接設定
hg config --global --edit

# 設定例(~/.hgrc)
[ui]
username = Your Name <[email protected]>
editor = vim
merge = vimdiff

[extensions]
color =
purge =
rebase =
shelve =

リポジトリの初期化と基本操作

# 新しいリポジトリを初期化
hg init my-project
cd my-project

# 既存リポジトリをクローン
hg clone https://hg.example.com/repository
hg clone ssh://[email protected]/user/repository

# 浅いクローン(--depth オプションはない代わりに)
hg clone --rev tip https://hg.example.com/repository

# ファイルの追加
echo "Hello Mercurial" > hello.txt
hg add hello.txt

# すべてのファイルを追加
hg add .

# ファイルの状態確認
hg status
# M = modified, A = added, R = removed, ? = untracked, ! = missing

# 変更差分の確認
hg diff
hg diff hello.txt
hg diff --rev 0:1  # リビジョン間の差分

# コミット実行
hg commit -m "Initial commit with hello.txt"
hg commit -A -m "Add all files and commit"  # add + commit

ブランチとブックマーク管理

# Named Branchの作成と管理
hg branch feature-authentication
echo "auth module" > auth.py
hg add auth.py
hg commit -m "Add authentication module"

# ブランチ一覧表示
hg branches
hg branches --active

# ブランチの切り替え
hg update default
hg update feature-authentication

# Bookmarkの作成(軽量ブランチ)
hg bookmark experimental-feature
hg commit -m "Experimental changes"

# ブックマーク一覧
hg bookmarks

# ブックマークの切り替え
hg update experimental-feature
hg update -r default

# ブランチのマージ
hg update default
hg merge feature-authentication
hg commit -m "Merge feature-authentication branch"

# グラフィカルなログ表示
hg log --graph
hg glog  # 短縮形

リモートリポジトリ操作

# リモートリポジトリの設定確認
hg paths

# デフォルトパスの設定
echo "[paths]" >> .hg/hgrc
echo "default = https://hg.example.com/repository" >> .hg/hgrc

# 変更をプッシュ
hg push
hg push -b feature-branch  # 特定ブランチのみ
hg push --new-branch      # 新しいブランチを含む

# 変更をプル
hg pull
hg pull -u  # pull + update

# インカミング変更の確認
hg incoming

# アウトゴーイング変更の確認
hg outgoing

# 特定リビジョンからプル
hg pull -r 123

高度な操作とワークフロー

# リビジョンの巻き戻し
hg rollback  # 最後のトランザクションを取り消し

# 変更の一時保存(shelve拡張必要)
hg shelve
hg shelve --list
hg unshelve

# ファイルの履歴確認
hg log filename.txt
hg log --follow filename.txt  # リネーム追跡

# 特定リビジョンのファイル表示
hg cat -r 123 filename.txt

# 注釈付きファイル表示(blame)
hg annotate filename.txt
hg blame filename.txt  # エイリアス

# リベース操作(rebase拡張必要)
hg rebase -s source_rev -d dest_rev

# チェリーピック(transplant拡張使用)
hg transplant 123

# パッチの作成と適用
hg export -r 123 > patch.diff
hg import patch.diff

# バンドルファイルでの変更セット交換
hg bundle --base 100 changes.hg
hg unbundle changes.hg

設定とカスタマイズ

# .hgrc設定ファイルの詳細設定
[ui]
username = Developer <[email protected]>
editor = code --wait
merge = vscode
ssh = ssh -C

[defaults]
log = --graph
status = --all

[alias]
ll = log --graph --template '{rev}: {desc|firstline}\n'
st = status
ci = commit
co = update

[extensions]
color =
pager =
progress =
rebase =
shelve =
purge =
histedit =

[color]
status.modified = cyan
status.added = green
status.removed = red
status.unknown = magenta

Webインターフェースとサーバー

# 内蔵Webサーバーの起動
hg serve
hg serve --port 8080 --address 0.0.0.0

# 設定ファイルでWebサーバー設定
[web]
port = 8080
address = localhost
name = My Repository
description = Project repository
contact = [email protected]
allow_push = *
allow_read = *

# hgwebを使用したマルチリポジトリホスティング
# /etc/mercurial/hgweb.config
[collections]
/repos = /path/to/repositories

[web]
style = gitweb
allow_push = *

フック機能とカスタマイズ

# .hg/hgrc でのフック設定
[hooks]
# pre-commit フック
pre-commit = python scripts/check-style.py

# commit メッセージフック
commit = echo "Committed changeset $HG_NODE"

# プッシュ後フック
post-push = curl -X POST https://api.example.com/webhook

# Python フックスクリプトの例
[hooks]
pre-commit.style = python:scripts.hooks.check_style

# scripts/hooks.py
def check_style(ui, repo, **kwargs):
    # スタイルチェックロジック
    if style_check_failed():
        ui.warn("Style check failed\n")
        return True  # コミットを拒否
    return False

プロジェクト固有のワークフロー

# 機能開発ワークフロー
hg update default
hg pull -u
hg branch feature/new-api
# 開発作業
hg commit -m "Implement new API endpoint"
hg update default
hg merge feature/new-api
hg commit -m "Merge feature/new-api"
hg push

# リリース管理ワークフロー
hg update default
hg branch release/v1.2.0
# リリース準備作業
hg commit -m "Prepare release v1.2.0"
hg tag v1.2.0
hg update default
hg merge release/v1.2.0
hg commit -m "Merge release v1.2.0"

# ホットフィックスワークフロー
hg update v1.1.0  # タグから開始
hg branch hotfix/critical-bug
# バグ修正
hg commit -m "Fix critical security bug"
hg tag v1.1.1
hg update default
hg merge hotfix/critical-bug
hg commit -m "Merge hotfix v1.1.1"

Python統合とスクリプト

# Python script での Mercurial操作
from mercurial import ui, hg, commands
from mercurial.context import workingctx

# リポジトリを開く
repo_ui = ui.ui()
repo = hg.repository(repo_ui, '.')

# ワーキングディレクトリの状態取得
wctx = workingctx(repo)
status = wctx.status()
print(f"Modified files: {status.modified}")
print(f"Added files: {status.added}")

# ログの取得
def get_recent_commits(repo, count=10):
    commits = []
    for i in range(min(count, len(repo))):
        ctx = repo[len(repo) - 1 - i]
        commits.append({
            'rev': ctx.rev(),
            'node': ctx.hex(),
            'desc': ctx.description(),
            'user': ctx.user(),
            'date': ctx.date(),
        })
    return commits

# プログラマティックコミット
def auto_commit(repo, message):
    repo_ui = repo.ui
    commands.commit(repo_ui, repo, message=message, addremove=True)

移行とインポート

# Gitリポジトリからの変換(hg-git拡張使用)
hg clone git://github.com/user/repo.git

# SVNリポジトリからの変換
hg convert --source-type svn https://svn.example.com/repo ./hg-repo

# FastExportを使用したGitからの移行
git fast-export --all | hg fastimport -

# 設定ファイルを使用した詳細変換
# convert.conf
[convert]
git.similarity = 90

# マップファイルでの作者変換
# authormap.txt
[email protected] = New Name <[email protected]>

hg convert --config convert.git.similarity=90 \
           --authormap authormap.txt \
           git-repo hg-repo