First steps with Mercurial

Mercurial is a good alternative to Git since I do not want to live in a world with only one distributed version control software... The use case here is to implement a complete set of configuration files (the default branch) that can be deployed a newly installed machine. Each specific configurations for a given machine will be pushed to the dedicated branch. This is not the most realistic scenario to play with a version control system but actually I do not have any others...

According to the quick start page of the official wiki of Mercurial, the first thing to do is to configure a proper email address. We also set the pager to less with some options to avoid quirks in display:

$ cat > .hgrc << EOF
[pager]
pager = LESS='FRX' less

[ui]
username = triaxx <triaxx@example.org>
EOF

The tree of our system configuration will be stored in the hidden directory .cfg. We initialize our Mercurial project in this directory:

$ mkdir .cfg
$ cd .cfg
$ hg init

We add our first file README.md. By default, all files that are not versioned are added by the add command. We can undo this adding by using the forget command and add again our file by explicitly passing its name to the add command:

$ cat > README.md << EOF
# cfg
* The default branch is for the common configurations.
* A branch named <hostname>--<osname> is for hostname's specific configurations.
EOF
$ hg add
adding README.md
$ hg forget README.md
$ hg add README.md
$ hg status
A README.md

This is time for the First^Initial commit!

$ hg commit -m "First commit"
$ hg commit --amend -m "Initial commit"

We want now push this commit to a remote repository. First we create a hg user on a remote host hg.example.org with no password. This user can remotely log on hg.example.org only with a private key. We use this user to remotely clone our repository with an empty working directory. This is an equivalent of the bare repository of Git:

$ ssh hg.example.org
$ su -
# groupadd hg
# useradd -g hg -m -d /srv/vcs/hg -s /bin/sh hg
# su - hg
$ ssh-keygen -t ed25519
$ cat .ssh/id_ed25519.pub > .ssh/authorized_keys
$ exit
# exit
$ scp hg.example.org:/srv/vcs/hg/.ssh/id_ed25519 ~/.ssh/hg # It is actually more complicated...
$ cat >> ~/.ssh/config << EOF
Host hg.example.org
    IdentityFiles ~/.ssh/hg
EOF
$ pwd
/home/triaxx/.cfg
$ cd ..
$ hg clone --noupdate .cfg ssh://hg@hg.example.org/cfg

We can now push changesets on our remote repository with the push command:

$ cd .cfg
$ mkdir etc
$ cp /etc/rc.conf etc # A refined rc.conf
$ hg add
$ hg commit -m "rc.conf: Add on default"
$ hg push ssh://hg@hg.example.org/cfg
pushing to ssh://hg@hg.example.org/cfg                    
searching for changes                
remote: adding changesets                                   
remote: adding manifests                                   
remote: adding file changes          
remote: added 1 changesets with 1 changes to 1 files

We would like to avoid systematically passing the path of the destination. Then we add the following lines in the .hg/hgrc file:

$ cat > .hg/hgrc << EOF
[paths]
default = ssh://hg@hg.example.org/cfg
EOF

For specific configurations on our host machine01, we create a dedicated branch on which we commit a more complete rc.conf file. Then we get back on the default branch:

$ hg branch machine01--netbsd
$ cp /etc/rc.conf etc
$ hg commit -m "rc.conf: Add on machine01--netbsd"
$ hg branches
machine01--netbsd              2:fee7344e8349
default                        1:f95b88577525 (inactive)
$ hg update default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg push --new-branch ssh://hg@hg.example.org/cfg
pushing to ssh://hg@hg.exxample.org/cfg
searching for changes
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 1 changesets with 1 changes to 1 files

If we want to pull and update files from a remote repository, we use the pull command:

$ hg pull -u

Page top