Mercurial

From Andreida

hg

Deciding which Source Management Tool to use?

Intro

It is VERY important you keep in mind that Mercurial has a repository and a working directory and these are different things. As always under Windows replace in paths '/' with '\' and ' with ".

Example:

mkdir d1
cd d1
hg init
echo [ui] > .hg/hgrc
echo username = ItsaMea >> .hg/hgrc
echo "test" > file1
hg add file1
hg commit -m 'adding test file'
cd ..
mkdir d2
cd d2
hg clone ../d1 .
dir
cd ..
cd d1
echo "test2" > file2
hg add file2
hg commit -m 'adding test file'
hg push ../d2
hg status
dir
cd ..
cd d2
dir
hg status

hg update
dir

As you can see, the changes in repository d1 are only seen in the working directory of repository2 after you do a push or pull AND update. The update will get the changes in repository d2 to the working directory of repository2. Depending on the circumstances, you will need to do a merge before you can push/pull.


So in this example we had four items to think about:

  • Repository d1
  • Working directory of repository d1
  • Repository d2
  • Working directory of repository d2

If you understand that push/pull work on repositories, NOT on working directories, you will have an easier life. I did - of course - not write this paragraph because I forgot about this and did not understand something happening until I thought it through. Of course not!

config file

  • Windows: C:\Users\<User>\mercurial.ini
  • Linux: ~/.hgrc

Username/Mail

If you are using the commandline, make sure to add to your config file:

[ui]
username = John Doe <john@example.com>

simple use

  • create a repository
hg init
  • create a file
echo "Hello World" > myTestFile
  • prepare it to be used by the next commit
hg add myTestFile
  • add it to the repository (under Windows: use " instead of ' for the comment)
hg commit -m 'adding a test file for test purposes and because testing is so tasty'
  • what happened in the long long history of this repository?
hg log
  • if you added the aliases I mention somewhere on this page, try
hg ll
  • create another file
echo "Bye bye World" > myTestFile2
  • change the first file
echo "Hello World 2" >> myTestFile
  • check the status of the files
hg status
  • commit all file with changes which are already managed by the repository
hg commit -m 'committing changes ... again? Work, Work'
  • check the status of the files
hg status

You will see that "hg commit" will commit all your changes to the repository. It will ignore new files until you manually add them with "hg add". You CAN use "hg commit" and give the files you want to commit as parameters. But normally you don't want to do that.

Create a repository from an existing project/directory

  • go into the root for the project and call there "hg init"
cd /d my-cool-project
hg init
  • create / copy a file "hgrc" inside .hg like the following
[ui]
ssh = ssh -C
username = Super Man <SuperMan@BatsCave.net>

[alias]
logline = log --template "{node|short} | {date|isodatesec} | {author|user}: {desc|strip|firstline}\n"
ll = logline -l 10
status = status --template status

[paths]
default   = d:\data\repos\mercurial\SuperMan
backup    = d:\data\repos\mercurial\SuperMan
r-netbook = ssh://r-netbook/work/SuperMan/
r-laptop  = ssh://r-laptop/work/SuperMan/
usb       = P:\SuperMan
  • Consider to use the aliases
  • The paths will be wrong for you, these should only give you an idea. Or 7.
  • In the root of your project call "hg add ."
cd /d my-cool-project
hg add .
  • commit the prepared adds (Linux uses ' instead of ", different paths too.. as always)
hg commit -m "initial adding of the project to Mercurial"

This might take a while, it is practically a copy of your current project.

Now you have a project which can use Mercurial. But you will probably want a server version of it in your backup folder. You have something like that, right? A folder which will be used to backup everything inside from time to time?

So... you'll clone your project to the backup folder: (it is: clone <source> <target>, so do NOT forget the '.')

hg clone . D:\data\repos\mercurial\my-cool-project

You do not want your server to have a checked out working directory, nobody will ever work on the server. NEVER!

cd /d D:\data\repos\mercurial\my-cool-project
hg up null

now try

cd /d my-cool-project
hg status
hg ll
hg push

aliases

mercurial command line log as one line per commit

Windows: add to .hg/hgrc:

[alias]
logline = log --template "{node|short} | {date|isodatesec} | {author|user}: {desc|strip|firstline}\n"
ll = logline

Linux: add to .hg/hgrc: (the only difference to Windows is " vs '

[alias]
logline = log --template '{node|short} | {date|isodatesec} | {author|user}: {desc|strip|firstline}\n'

Weird formatting of status output

If you get something which looks like bad readable links if you do

hg status

then you probably don't want that. I do not understand the reason for it and I am not sure my "solution" is the correct way to do it. But it works:

 [alias]
 status = status --template status

ssh

Normally you will want to use the default OS ssh. So add the following to the config file:

[ui]
ssh = ssh -C

The "-C" seems to enable compression. Not sure yet, but I keep it for now.

IF you can normally ssh to the other machine with

ssh v-rooster

then now you should be able to do a

hg -v push ssh://v-rooster/work/repo1/

or pull or clone or whatever you want to do.

You can give a name and/or port like this:

hg -v push ssh://user@v-rooster:port/work/repo1/

but it would make more sense to configure your port to connect correctly. Example under Windows 10, modify your C:\Users\<user>\.ssh\config

 Host v-rooster
   HostName        1.2.3.4
   User            meaMario
   Port            22
   IdentityFile   C:\Users\<user>\.ssh\id_rsa-no-pw

paths

If you don't want to write the server and path all the time, add the following to the config file:

[paths]
default = ssh://v-deb-dev2/work/src/
v-deb-dev1 = ssh://v-deb-dev1/work/src/
v-deb-dev2 = ssh://v-deb-dev2/work/src/
v-deb-dev3 = ssh://v-deb-dev3/work/src/

You guessed it, 'default' is the entry which is used, when you don't give a remote target. It is NOT necessary to have it as normal path AND default, but I like it that way.

If you want to see these with hg:

hg paths

If you clone a repository, your default is of course the source of the clone.

clone via ssh to remote

Somehow the Windows .ssh\config was completely ignored. I had to start the putty pagent with the private key needed and give the data manually, not via the 'hg paths' shortcut. THEN I could use

hg clone . ssh://username@127.0.0.1:20023/work/src/

This created a repository on that system. Don't forget to

hg update

if you want to see the data. You will want to do something about .hg/hgrc too.

(In the example above I am using the local ip and a weird port because I ssh into a locally running VirtualBox with my development environment.)

copy/move

use

hg cp source target
hg mv source target
hg mv oldFile NewFile
hg mv project directory

empty work directory

Normally you have all the history in the .hg directory and than a checked out version directly in the repositories root directory.

If you want it to be empty, for example because it is just like a server, no need need for a working directory with checkout:

hg update null

Only the .hg directory will remain.

TortoiseHG

Why does hg not work?

After you installed TortoiseHG, add the path to the install directory of TortoiseHG to the PATH variable. (Start/Settings/System/About/System Info/Advanced system settings/Environment Variables...)

ignore

(source)

In the root of the repository you can put a file ".hgignore". Here you can use normal ("glob") patterns or regular expressions, somehow. For glob:

syntax: glob
*.aux
*.log
*.out
*.synctex.gz

From now on you will not see untracked files with these extensions if you use

hg status 

But if you use

hg status -A

Then you'll see the files with an "I" for ignored.

Manage hgrc with Mercurial

Everything in .hg does NOT have a history in Mercurial. Depending on your circumstances, you want the history of hgrc or even be able to copy/paste another hgrc to your current installation without a hassle. You can do it:

  • in the main directory of your Mercurial repository create a directory called ".hg-configs-managed".
  • move your current .hg/hgrc to .hg-configs-managed/hgrc-MY-CORPORATION-PC01
  • create a link .hg/hgrc which points to .hg-configs-managed/hgrc-MY-CORPORATION-PC01
  • put .hg-configs-managed/hgrc-MY-CORPORATION-PC01 into Mercurial ("hg add...")
  • repeat this for every installation, so you'll get a lot of files in .hg-configs-managed but only one hgrc in .hg

Create the link with Linux

cd .hg
ln -s ../.hg-configs-managed/hgrc-MY-CORPORATION-PC01 hgrc

Create the link with Windows 10

cd .hg
mklink /H hgrc ..\.hg-configs-managed\hgrc-MY-CORPORATION-PC01


Mercurial does not recognize changes from hardlinks for files outside the repository. So, if you have the needed rights, use Softlinks (mklink without /H), because you want to be consistent and not have to think about which files got a softlink and which ones got a hardlink.

Questions

Get a managed file back which I deleted

I deleted a file and just want Mercurial to get it again:

hg revert <file>

Diff abort with "not under root"

  • pull/push
cd myLocalRepository
hg pull remoteRepository
  • diff
cd myLocalRepository
hg diff remoteRepository
ERROR

Diff is mostly used for differences between revisions. And it is used for differences between files. If you just point it to a repository, chances are, the command will fail. There were cases where the command did not give me an error. But do NOT use diff as test for your connection to a remote repository.

If you need a test command, use something like

hg outgoing otherRepository