Mercurial SCM (Hg) Toomas Laasik
1.06.2018 Mercurial
Mercurial is a free, distributed source control management tool, like git Mercurial
Mercurial is a free, distributed source control management tool, like git
Philosophy and key points:
● Usability first, has consistent syntax and help Mercurial
Mercurial is a free, distributed source control management tool, like git
Philosophy and key points:
● Usability first, has consistent syntax and help ● Each command does one thing Mercurial
Mercurial is a free, distributed source control management tool, like git
Philosophy and key points:
● Usability first, has consistent syntax and help ● Each command does one thing ● History should be preserved Mercurial
Mercurial is a free, distributed source control management tool, like git
Philosophy and key points:
● Usability first, has consistent syntax and help ● Each command does one thing ● History should be preserved ● Works well on all major OSes, including Windows Mercurial
Mercurial is a free, distributed source control management tool, like git
Philosophy and key points:
● Usability first, has consistent syntax and help ● Each command does one thing ● History should be preserved ● Works well on all major OSes, including Windows ● Easy to install and configure. It just works Mercurial
Mercurial is a free, distributed source control management tool, like git
Philosophy and key points:
● Usability first, has consistent syntax and help ● Each command does one thing ● History should be preserved ● Works well on all major OSes, including Windows ● Easy to install and configure. It just works ● Extensible (but base version is often enough) Mercurial. Who uses it?
● Why? Because git had trouble handling huge repositories ● Facebook has its own extensions for Hg
Mozilla Firefox
● 10+ million LOC Mercurial anatomy
Hg repository consists of a working directory and .hg/ directory
Working directory is a copy of the project's files at a given point in time plus uncommited edits (rev 2 is a parent of working directory) Mercurial anatomy
.hgignore lists files that are not syntax: glob revisioned. Same as .gitignore *.sln Temp/* It is tracked as any other file site.cache Mercurial anatomy
.hgtags relates revisions to given 85a9d168e7aa1cd2e... build_273 human readable tag names 16c18a4302b89afd2... build_305
It is tracked as any other file Mercurial anatomy
Commit records state of the working directory relative to its parent in a new changeset (rev 4). That changeset will become new parent for working directory.
Rev 4 is now a branch because “line of development diverged” Mercurial anatomy
A changeset:
● is an atomic group of related changes to multiple files ● has a revision number and hash id ● has one or two parents (merge)
Changeset without children is called a head, latest head is called a tip Mercurial anatomy
Hg is a distribured SCM
Each team member has their own cloned repository. Sometimes more than one
No central repository is needed, but often it is convenient to have a passive central repository (eg BitBucket)
https://homes.cs.washington.edu/~mernst/advice/version-control.html Tools
Hg has CLI interface (hg
There are plugins to integrate Hg into all major IDEs: Eclipse, Visual Studio, IntelliJ, etc
There are multiple standalone GUIs for Hg. One of them is TortoiseHg:
● hg CLI tool ● TortoiseHg Workbench ● Windows Shell extension ● TortoisePlink for SSH tunnel Tools. TortoiseHg Setup and config
Install TortoiseHg ~/.hgrc or Mercurial.ini
Edit user wide config and add [ui] username = Toomas Laasik
Each repository has its own .hg/hgrc file that has repo specific lines and can override parts of user config Setup and config
Normally access to remote ~/.hgrc or Mercurial.ini private repo prompt you for [ui] password. It may be a good username = Toomas Laasik
[extensions] strip =
An actual config I use --> Workflows
Workflow is a way how you, your team and others use SCM for a project.
Some basic workflows (https://www.mercurial-scm.org/guide):
● Log keeping ● Lone developer with nonlinear history ● Separate features ● Sharing changes
Many workflows can be mixed and matched.
Each team usually has a custom workflow best suitable for them Log keeping workflow
● Use Case: Look back when you did which changes ● 1 developer, 1 local repo
Very basic, this is here just to get accustomed to syntax Log keeping workflow hg init - create repo $ mkdir uthg/ $ cd uthg/ hg add
$ hg commit Log keeping workflow hg status - show changes $ echo world >> hello.txt in the working directory $ echo Read this > README $ hg status Commit changes M hello.txt ? README
$ hg commit Oops, forgot to add $ hg add README! --amend flag adding README lets you recommit last change $ hg commit --amend saved backup bundle to c:\work\uth... Log keeping workflow hg status - show changes $ echo world >> hello.txt in the working directory $ echo Read this > README $ hg status Commit changes M hello.txt ? README
$ hg commit Oops, forgot to add $ hg add README! --amend flag adding README lets you recommit last change $ hg commit --amend saved backup bundle to c:\work\uth... There is also hg rollback Log keeping workflow hg diff - see changes $ echo asdasd >> hello.txt $ hg diff hg revert
$ hg revert hello.txt $ hg status ? hello.txt.orig
$ rm *.orig Log keeping workflow hg cp
● Use Case: Go back at times and work onward from there ● 1 developer, 1 local repo
Basic, but shows how automatic anonymous branching and merging works. Lone developer with nonlinear history hg update
After commit we have two heads. Later on heads need to be merged or closed Lone developer with nonlinear history hg merge - merge working $ hg merge directory with another merging hello.txt and copy_of_hello.txt to copy_of_.. merging hello.txt and renamed_hello.txt to renamed_.. revision. 0 files updated, 2 files merged, 0 files removed, 0.. (branch merge, don't forget to commit) No conflicts. $ hg commit -m “Merge” Here no arguments are given, because there we are on one head and there is only exactly one other head. Lone developer with nonlinear history hg merge - merge working $ hg merge directory with another merging hello.txt and copy_of_hello.txt to copy_of_.. merging hello.txt and renamed_hello.txt to renamed_.. revision. 0 files updated, 0 files merged, 0 files removed, 2.. (branch merge, don't forget to commit) Merge conflicts! If hg couldn’t resolve them $ hg resolve --list automatically you need to somefile.txt do it manually, mark them (edit files listed to manually resolve conflicts or resolved and commit retry automatic resolving hg resolve somefile.txt)
Nicer to do in GUI $ hg resolve --mark somefile.txt
$ hg commit -m “Merge” Lone developer with nonlinear history hg merge - merge working $ hg merge directory with another merging hello.txt and copy_of_hello.txt to copy_of_.. merging hello.txt and renamed_hello.txt to renamed_.. revision. 0 files updated, 0 files merged, 0 files removed, 2.. (branch merge, don't forget to commit) Merge conflicts! If you can’t resolve conflicts or $ hg resolve --list just want to cancel merge, somefile.txt then update to some other (edit files listed to manually resolve conflicts or revision retry automatic resolving hg resolve somefile.txt)
$ hg update --clean Lone dev...
Merge conflict resolving in TortoiseHg
Next: repo branches as TortoiseHg shows it Lone developer with nonlinear history Separate features
● Use Case: Work on several features in parallel ● 1 developer, many repos
Each feature is kept and developed in cloned repo.
In practice you can have many variations of it:
● stable, feature1, feature2, … ● stable, testing, features
(Using named branches gives somewhat similar workflow) Separate features hg clone
$ cd uthg_feature1 $ hg mv renamed_hello.txt hello.txt $ echo Feature_1 >> hello.txt $ hg status A hello.txt R renamed_hello.txt
$ hg commit -m "Added feature 1" Separate features Separate features hg incoming
$ hg pull ..\uthg_feature1 pulling from ..\uthg_feature1 ... (run 'hg update' to get a working copy) Separate features
If there where no changes $ hg update tip in main uthg we can just 1 files updated, 0 files merged, 1 files removed, 0.. update working directory to the changeset we just pulled hg update tip - update working directory to latest head (tip) Separate features workflow
If there where changes $ hg update tip in main uthg repo we have $ hg merge to merge heads instead 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit)
Could use hg heads and $ hg commit -m "Merged feature 1" other CLI commands, but a nice GUI gives much better overview Separate features workflow Sharing changes workflow
● Use Case: Share your changes, receive changes made by others ● many developers, many repos
Many ways for doing it:
● no central repo, devs connect directly ● exchange patches ● use shared passive repo Sharing changes - hg serve hg serve - starts a simple $ hg serve stand-alone webserver listening at http://192.168.1.199:8000/ (bound..
Read only (no push unless specifically allowed)
No access control Sharing changes - hg serve
Useful for connecting directly $ hg serve to another dev repo in LAN. listening at http://192.168.1.199:8000/ (bound..
Even if using remote repo ### Other developer like BitBucket, occasionally this is useful for cases when: $ hg incoming http://192.168.1.199:8000 comparing with http://192.168.1.199:8000/ ● service is down searching for changes ● quickly restoring repo no changes found
after recover from disk ### or failure $ hg clone http://192.168.1.199:8000 ### or $ hg pull http://192.168.1.199:8000 Sharing changes - patches
Sending patches is useful if $ hg log you don’t have write access ... $ hg export -r 5:7 > changes.diff to target repo ### Other developer hg export … >
### test if there are no issues, then hg import
Using shared repo is very $ hg clone https://[email protected]/tooms/uthg similar to one-local-repo-per- ... feature workflow
The only differences:
● repo is in internet ● local repos are user repos, not feature repos Sharing changes - shared repo
Setup once: $ hg clone https://[email protected]/tooms/uthg ... 1. create repo over web 2. give access to devs $ hg pull ... Then each dev: $ hg merge ... 3. clones the repo $ hg push 4. push and pull regularly ... Sharing changes - shared repo How we use Mercurial at Interactive Fate
One Unity3D project
4 people team. Only one has SW development background and writes code (me)
Repo is 3.5Gb and has 1.5 years of history in it, most is binary and yaml
About 10-20 commits/merges per work day
Shared repo hosted by xp-dev.com (was in BitBucket.org, but it had 2Gb limit)
No issue tracking integration Real world challenges - lots of binary files
Photoshop PSD files are not kept in Hg repo, but on local drive
● some PSDs are hundreds of MB ● risky business ● final PNG files are in repo
Still, checked out repo can be directly opened/imported in Unity
Mercurial has bigfiles extension, but we don’t use it. Workflow not easy enough Real world challenges - hardware failures
One team member used faulty external USB HDD
● disconnected at will, corrupting parts of repo ● we saw changesets without parents, commited files reapparing as changed,etc ● to restore the repo we cloned .hg/ manually and changed .hg/hgrc afterwards
Occasionally we didn’t have internet or BitBucket was down
● Everyone kept working on their repo ● I used hg serve on LAN to let them get my changes Real world challenges - brances and tags
2 branches:
● “default” - bleeding edge code lives here ● “indiegogo” - branch for indiegogo release, later we plan to make more release branches ● code has been merged between those both ways
Tags:
● for public builds, like “build_305” from indiegogo branch ● build number comes from Unity Cloud Build that pulls code from xp-dev.com, but we have to add the tag manually Real world challenges - file renames, mass changes
Unity creates meta file for every other file, it’s a problem if viewed from hg side
● hg mv is tedious or sometimes impossible ● solution: TortoiseHg variant of hg addremove --similarity 100
Some code changes trigger serialized asset file changes
● example: adding “idleLogMessage” to crew causes 20 crew asset changes ● problem. sometimes those asset changes are delayed ● solution: be extra careful to ensure assets get updated ● even still, sometimes small code change causes hundreds of changes for another developer who just did pull Summary
By now you should know about:
● What is Mercurial and how it works on basic level ● Know basic workflows for team and single developer ● Know about some hosting options ● Know about some real life challenges that you may face when using Hg
Questions?