• # Intermediate Advanced Mercurial DVCS (Hg) tips

Engines and Middleware

• Posted By Gru

# Proper installation:

This whole article is based on Windows usage. You have a couple of options: 1. Download only the executable from the Mercurial website: this is fine and will give you the latest version. However, there is no GUI with it. 2. Download SourceTree and use Hg from the terminal that comes with it. It does not add the path to hg executable to the Path system variable, so you have to do it manually. Also, you will not get the most recent version, depending on which version of SourceTree you have installed. The best version of SourceTree for Windows at the time of writing, in my opinion, is 1.7.0.3, but it comes with an outdated version of Hg. You can tell it to use the 'System Mercurial' (whatever other Hg installation you have on your system), but then some things won't work (like hgflow) without manual fiddling. 3. Download TortoiseHg. It is useful with a Visual Studio extension that I will explain below. I really haven't used it much because of the archaic interface, but it has its following. For beginners, I would actually recommend both (2) and (3), SourceTree for everyday use and TortoiseHg for integration with Visual Studio. To check which hg you have installed, type in: where hg and you will get a path to hg executable. If you don't get anything and you know it is installed, you need to add it to your Path system variable. If you use Visual Studio in your development, you may want to have an extension for it which helps a bit with Hg repositories. There are a couple of options, but my personal favorite is VisualHg2, as here: https://bitbucket.org/lmn/visualhg2. I would recommend opening a small window with status and docking it in a corner: it shows you which files are changed and provides some common options in the context menu. However, it relies on you having installed TortoiseHg previously, thus the recommendation I mentioned above, so all the operations chosen from Visual Studio menu will be diverted to TortoiseHg. Besides graphical tools, for learning, it is best to use the command line. I am also not a fan of the default Windows cmd console, so I strongly recommend installing a terminal emulator such as ConEmu (another personal favorite of mine). Highlights include: "knowing" if you want to select a line or a rectangular space, automatic copy, allowing paste with Ctrl+V, multiple tabs split to sides and bottom, user themes. Just install it and select the default theme, with Consolas 11pt font, and it will look and work great. You may also want it integrated into the Right-Click context menu, which it isn't by default. You do that by going into Settings > Integration and clicking Register on the top option. Here is how I use these tools. I open a VS project and Right-Click on the Solution "Open Folder in File Explorer". This opens the folder where the project is. There I Right-Click and chose "ConEmu here" and I can command line from there really quickly. The same works from within Unity, with the "Show in Explorer" option. All the other external tools are optional, but I still use SourceTree sometimes. Update: In the meantime I have discovered another, faster way to open the console at the current project. There is a free Visual Studio extension called Open Command Line, by Mads Kristensen, which can be configured to work nicely with ConEmu. All I do now is press Alt+Space in Visual Studio and ConEmu is opened at the root of the current project, ready for Hg commands.

# Where to learn it:

## Aliases:

This is my favorite part, aliases make things so easy and quick, and allow for nice customization. They are personalized shorthands for certain commands with certain options. Aliases are defined in their own header [alias], they start with the name of the alias followed by '=' and then the parameters that you'd normally supply to hg. If you start an alias with '!' then that alias is instead a System command, and what follows you'd normally type in the shell you're executing the hg command from. This means the aliases you use may not be cross platform. You don't even have to type the whole command/alias every time, just the distinguishable part. clean = !hg revert --all --no-backup && hg purge Note: It's signs for (and) and (and) above. The editor here seems to have converted it... Hg already has an alias clean that is a synonym for purge, but I decided to steal it. This creates no problems and 'just works'. This alias has 2 parts: first, it reverts all files to the state of the last commit; second, it erases all the files found not known to Hg. The second part comes in handy with Unity because of .meta files. The commands are separated by '&&' which means you'd normally do something like this in 2 steps. Also, note the no-backup option. This will really clean up the working directory, so you've been warned. pushbranch = push --rev . In Hg, as opposed to Git, you push all branches when you do a push. This may not be what you want (though it normally is). With this alias you just push the branch you're currently on. slog = log --template "\x1B[4m{pad('({rev})',6,' ',True)} \x1B[5m{node|short} \x1B[8;9m{word(0, '{date|isodate}')} {word(1, '{date|isodate}')} \x1B[6m=> {author|user} {ifcontains(rev, revset('.'), '\x1B[8;9m@', ':')} \x1B[7m{desc|firstline} \x1B[8;9m[{branch}]{if(tags, ' [{tags}]')}{if(bookmarks, ' [{bookmarks}]')}\n" Note: the whole command is a one-liner. slog is my personal beast! It's a shorthand of short log. The original log command produces quite line-heavy output, so I prefer output like this: Fancy, hmmm? It will also show you the current commit you're on with the '@' sign. You would have to take a look at the templating mechanism to understand what this actually does, but the more confusing part are terminal codes starting with \x1B. This presumes you've enabled the color extension as explained above. After the '[' sign the code will determine the color. You can read more about terminal codes here: https://en.wikipedia.org/wiki/ANSI_escape_code This is probably my #1 favorite hg command now, and you limit the output like this hg slog -l 5. I have limited the output already with the -l 15 you can see above, but if you specify it in your command it will take precedence. glog = log -l 15 -G --template "\x1B[4m({rev}) \x1B[5m{node|short} \x1B[8;9m{word(0, '{date|isodate}')} {word(1, '{date|isodate}')} \x1B[6m({author|user}) {ifcontains(rev, revset('.'), '\x1B[8;9m@', ':')} \x1B[7m{desc|firstline} \x1B[8;9m[{branch}]{if(tags, ' [{tags}]')}{if(bookmarks, ' [{bookmarks}]')}\n" Note: the whole command is a one-liner. glog - the graphical log is even better: You can also see 'closed branches' displayed differently on the tree. This arguably replaces any need for a visual tool in most cases (depending on the complexity of your workflow). blame = annotate --user -number A small optional alias that shows who actually changed which line of the supplied file. SourceTree has this option, but I find this really quick, if not necessarily frequently used. noorig = !del /S/P *.orig When you have merge conflicts you may leave .orig files laying around after you do the merge. This a shortcut on system command del, and it will prompt you for each individual file and search subdirectories. You would call it like hg noorig. here = log -r . Just a quick alias to show you the current commit you're working off of. You could also change it for here= slog -r . if you liked that compact output from before, but I don't see much point in this case. plog = log --style=compact --patch -r . As in patch-log. It shows the 'patch view' of the last commit relative to the commit before it. The patch view is very useful, it shows differences very colorfully. qlist = !echo \033[34m Series: | cmdcolor && hg qseries && echo \033[95m Applied: | cmdcolor && hg qapplied Note: It's signs for (and) and (and) above. The editor here seems to have converted it... To get this to work you need to download the small utility from here (https://github.com/jeremejevs/cmdcolor) and place it in your Path. What it does is it allows for the same coloration we mentioned in the templating alias, but the cmd does not actually support that kind of coloration when output is printed to it. It does work, but the range of options is somewhat limited. Here is a list of colors with codes: Beyond that, it simply joins the outputs of 2 commands used together commonly when working with patches. upsafe = update -check When changing the current working directory, unless the option -check is supplied it will try to carry over the unclean content into the new commit. This seems somewhat out of line with Hg's "safety first" policy because in Gamedev environments it can create a bit of havoc (unconnected asset references, etc.). It's better to just use hg ups to be safe and let Hg warn you if there are any outstanding changes. fa = forget "set:added()" As in forget-all. If you added a range of files by mistake, this is the quickest way to "un-add" them all. stnm = status -X "**.meta" Unity's .meta files are a bit annoying when you have to look at the file system. They also create some visual clutter when reviewing changes either in SourceTree or from the command line. This is a quick shorthand to exclude the .meta files from the output of the status command. gst = !hg status | PathToTree /s /c | cmdcolor Now for the real kicker, graphical status. For this, you would need my little utility downloaded from here: https://bitbucket.org/sirgru/pathtotree/downloads and also the cmdcolor program mentioned before (optional). Instead of showing the linear list of files in the output of the status and building the tree in your head, why not let the computer display the tree? This is especially useful to us in GameDev because we tend to have somewhat deep hierarchies of folders. You can read the details about the utility on Bitbucket, so I won't repeat it here. The output you get by using hg gst will be like in the lower part of the image. gstnm = !hg status -X "**.meta" | PathToTree /s /c | cmdcolor As in "graphical status no meta files". This combines the outputs of the last 2 aliases: it omits the .meta files and builds the tree. close = commit -m "Closed branch" --close-branch When you do feature branches, at some point you'll - of course - want to merge them back into the original. If you don't close feature branches first, they will show in the output of hg heads and hg branches. This may not be what you want, so you have to manually close the branch, preferably before merging it back, by creating another commit with --close-branch option. This option is a shorthand for such boilerplate commit.

## Bonus tip:

When you rename a file tracked by Hg, it needs to know it is the same file and not deletion + addition if you want to keep its history. This is determined by 'similarity factor': if it's just the rename of the file it is 100% similar. However, when working with Unity it's never just a simple rename: if you rename the source file you have to rename the class too because it would not work otherwise. SourceTree seems to be stuck at 100% similarity and I haven't seen the way to change that. You need to do something like hg addrem and the system should automatically use some similarity lower than 100%. To achieve that, you put in this alias: [defaults] addremove = --similarity 90 Note: its '[defaults]'. Now both in SourceTree and Hg command line addrem command will look for similarity of "90% +". Bonus tip 2: Setting up pre-hook to not allow commits when there are unknown files: By default, Hg will not warn you about the files created, but not yet added. This can result in a situation where you have created a commit, but that commit does not include newly created files. Everything seems fine, but the push is incomplete.... and you transfer to a new machine and you're missing files, or your colleagues are confused. This happened to me a couple of times, so I looked for ways to avoid it in the future. Admittedly, it's not hard to check for status every time before a commit, but you can still forget it sometimes. I usually dealt with this with a com --amend option after realizing I forgot to hg add, but there is a saying "if something bothers you more than 3 times within a week, make sure to fix it." So, here's how. First, you will need my command line utility. It's a trivial thing that only returns a status code based on whether there was some standard input piped in. AnyStdIn.zip This will only work on 64-bit OS-es (Windows). Make sure it's on your Path system variable. Second, you need to modify your .hg/hgrc file inside the repository that you want this hook to be relevant to. I prefer to have this for all repos, so I put it inside mercurial.ini file. What this does is creates a "hook" that will fire before the commit event, it will list all "untracked files", and if there are any they will be piped into AnyStdIn.exe, which will return status code 1 and abort the commit. [hooks] precommit.No_Untracked_Files = hg st -u | AnyStdIn Note: it's '[hooks]' And... that's it. If there are untracked files, the message will be something like: abort: precommit.No_Untracked_Files hook exited with status 1 If for any reason you'd want to avoid this check you'd have to temporarily comment out this hook's line.

# Conclusion:

I hope you have enjoyed this article and tried these commands. Reading about these things is really easy, but in the heat of development, problems in this area are really not welcome. That's why it's important to be properly prepared and practiced when it comes to these things, and have a standardized, reliable, understood workflow in your GameDev shop. If you're finding this article helpful, stop by here where I have more simple gamedev tips and tutorials, and consider our asset Dialogical on the Unity Asset store for your game dialogues.

Update 1 (21.01.2017): Style updates, some new content since first publish.

Report Article

## User Feedback

Let me know what you think...

##### Share on other sites

I don't use Hg, but this look pretty neat, coming from git.

## Create an account

Register a new account

• ### Game Developer Survey

We are looking for qualified game developers to participate in a 10-minute online survey. Qualified participants will be offered a \$15 incentive for your time and insights. Click here to start!

• 0
• 0
• 4
• 3

• 15
• 20
• 20
• 11
• 9
×