mercurial scm (hg) - ut · setup and config install tortoisehg edit user wide config and add at...
TRANSCRIPT
Mercurial SCM (Hg)Toomas Laasik
1.06.2018
MercurialMercurial is a free, distributed source control management tool, like git
MercurialMercurial is a free, distributed source control management tool, like git
Philosophy and key points:
● Usability first, has consistent syntax and help
MercurialMercurial 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
MercurialMercurial 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
MercurialMercurial 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
MercurialMercurial 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
MercurialMercurial 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?Facebook
● Why? Because git had trouble handling huge repositories● Facebook has its own extensions for Hg
Mozilla Firefox
● 10+ million LOC
Mercurial anatomyHg 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 revisioned. Same as .gitignore
It is tracked as any other file
syntax: glob*.slnTemp/*site.cache
Mercurial anatomy.hgtags relates revisions to given human readable tag names
It is tracked as any other file
85a9d168e7aa1cd2e... build_27316c18a4302b89afd2... build_305
Mercurial anatomyCommit 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 anatomyA 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 anatomyHg 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
ToolsHg has CLI interface (hg <command> …)
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 configInstall TortoiseHg
Edit user wide config and add at least who you are (~/.hgrc)hg config --edit
Each repository has its own .hg/hgrc file that has repo specific lines and can override parts of user config
~/.hgrc or Mercurial.ini
[ui]
username = Toomas Laasik <[email protected]>
Setup and configNormally access to remote private repo prompt you for password. It may be a good idea to use keys instead
An actual config I use -->
~/.hgrc or Mercurial.ini
[ui]
username = Toomas Laasik <[email protected]>
ssh = tortoiseplink.exe -ssh -i "c:\keys\toomas.ppk"
[extensions]
strip =
WorkflowsWorkflow 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 workflowhg init - create repo
hg add <filename> - add a file on the next commit. Without filename all files are added
hg commit - commit changes to default branch
hg log - show revision history
$ mkdir uthg/
$ cd uthg/
$ echo Hello > hello.txt
$ hg init
$ hg add hello.txt
$ hg commit -m "First commit"
$ hg log
changeset: 0:f4d00ef06737
user: Toomas Laasik <[email protected]>
date: Tue May 29 21:47:54 2018 +0300
summary: First commit
Log keeping workflowhg status - show changes in the working directory
Commit changes
$ echo world >> hello.txt
$ echo Read this > README
$ hg status
M hello.txt
? README
$ hg commit
Log keeping workflowhg status - show changes in the working directory
Commit changes
Oops, forgot to add README! --amend flag lets you recommit last change
$ echo world >> hello.txt
$ echo Read this > README
$ hg status
M hello.txt
? README
$ hg commit
$ hg add
adding README
$ hg commit --amend
saved backup bundle to c:\work\uth...
Log keeping workflowhg status - show changes in the working directory
Commit changes
Oops, forgot to add README! --amend flag lets you recommit last change
There is also hg rollback
$ echo world >> hello.txt
$ echo Read this > README
$ hg status
M hello.txt
? README
$ hg commit
$ hg add
adding README
$ hg commit --amend
saved backup bundle to c:\work\uth...
Log keeping workflowhg diff - see changes
hg revert <filename> - reverts uncommited changes. Creates backup file with orig extension (disable with -C flag)
$ echo asdasd >> hello.txt
$ hg diff
diff -r 9fc99ad93c03 hello.txt
--- a/hello.txt Tue May 29 23:25:44 2018 +0300
+++ b/hello.txt Wed May 30 00:55:13 2018 +0300
@@ -1,2 +1,3 @@
Hello
world
+asdasd
$ hg revert hello.txt
$ hg status
? hello.txt.orig
$ rm *.orig
Log keeping workflowhg cp <old> <new>hg mv <old> <new> - copy or move file without loosing revision history. Don’t forget to commit!
hg summary - show working directory state
$ hg cp hello.txt copy_of_hello.txt
$ hg mv hello.txt renamed_hello.txt
$ hg summary
parent: 1:9fc99ad93c03 tip
Added readme, changed hello
branch: default
commit: 1 renamed, 1 copied
update: (current)
$ hg commit -m “copy and rename”
Log keeping workflowhg log -G - show revision history with graph
$ hg log -G
@ changeset: 2:4ca546cbe96a
| tag: tip
| user: Toomas Laasik <[email protected]>
| date: Wed May 30 01:36:00 2018 +0300
| summary: copy and rename
|
o changeset: 1:9fc99ad93c03
| user: Toomas Laasik <[email protected]>
| date: Tue May 29 23:25:44 2018 +0300
| summary: Added readme, changed hello
|
o changeset: 0:f4d00ef06737
user: Toomas Laasik <[email protected]>
date: Tue May 29 21:47:54 2018 +0300
summary: First commit
Lone developer with nonlinear history● 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 historyhg update <rev> - update working directory to changeset (needs clean working directory)
After commit we have two heads. Later on heads need to be merged or closed
### continuing from code above
$ hg update 1
$ echo Hello world! > hello.txt
$ hg commit -m "Put hello on one line"
created new head
Lone developer with nonlinear historyhg merge - merge working directory with another revision.
No conflicts.
Here no arguments are given, because there we are on one head and there is only exactly one other head.
$ hg merge
merging hello.txt and copy_of_hello.txt to copy_of_..
merging hello.txt and renamed_hello.txt to renamed_..
0 files updated, 2 files merged, 0 files removed, 0..
(branch merge, don't forget to commit)
$ hg commit -m “Merge”
Lone developer with nonlinear historyhg merge - merge working directory with another revision.
Merge conflicts! If hg couldn’t resolve them automatically you need to do it manually, mark them resolved and commit
Nicer to do in GUI
$ hg merge
merging hello.txt and copy_of_hello.txt to copy_of_..
merging hello.txt and renamed_hello.txt to renamed_..
0 files updated, 0 files merged, 0 files removed, 2..
(branch merge, don't forget to commit)
$ hg resolve --list
somefile.txt
(edit files listed to manually resolve conflicts or
retry automatic resolving hg resolve somefile.txt)
$ hg resolve --mark somefile.txt
$ hg commit -m “Merge”
Lone developer with nonlinear historyhg merge - merge working directory with another revision.
Merge conflicts! If you can’t resolve conflicts or just want to cancel merge, then update to some other revision
$ hg merge
merging hello.txt and copy_of_hello.txt to copy_of_..
merging hello.txt and renamed_hello.txt to renamed_..
0 files updated, 0 files merged, 0 files removed, 2..
(branch merge, don't forget to commit)
$ hg resolve --list
somefile.txt
(edit files listed to manually resolve conflicts or
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 featureshg clone <src> <dst> - makes a clone of a repo. Can use folders, URLs
### continuing from code above
$ cd ..
$ hg clone uthg uthg_feature1
updating to branch default
3 files updated, 0 files merged, 0 files removed, 0..
$ 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 featureshg incoming <src> <dst> - show new changesets found in source
hg pull <src> - pull changes from source
$ cd ..\uthg
$ hg incoming ..\uthg_feature1
comparing with ..\uthg_feature1
searching for changes
changeset: 5:41e754a425d5
tag: tip
user: Toomas Laasik <[email protected]>
date: Thu May 31 21:01:39 2018 +0300
summary: Added feature 1
$ hg pull ..\uthg_feature1
pulling from ..\uthg_feature1
...
(run 'hg update' to get a working copy)
Separate featuresIf there where no changes in main uthg we can just update working directory to the changeset we just pulled
hg update tip - update working directory to latest head (tip)
$ hg update tip
1 files updated, 0 files merged, 1 files removed, 0..
Separate features workflowIf there where changesin main uthg repo we have to merge heads instead
Could use hg heads and other CLI commands, but a nice GUI gives much better overview
$ hg update tip
$ hg merge
1 files updated, 0 files merged, 1 files removed, 0
files unresolved
(branch merge, don't forget to commit)
$ hg commit -m "Merged feature 1"
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 servehg serve - starts a simple stand-alone webserver
Read only (no push unless specifically allowed)
No access control
$ hg serve
listening at http://192.168.1.199:8000/ (bound..
Sharing changes - hg serveUseful for connecting directly to another dev repo in LAN.
Even if using remote repo like BitBucket, occasionally this is useful for cases when:
● service is down● quickly restoring repo
after recover from disk failure
$ hg serve
listening at http://192.168.1.199:8000/ (bound..
### Other developer
$ hg incoming http://192.168.1.199:8000
comparing with http://192.168.1.199:8000/
searching for changes
no changes found
### or
$ hg clone http://192.168.1.199:8000
### or
$ hg pull http://192.168.1.199:8000
Sharing changes - patchesSending patches is useful if you don’t have write access to target repo
hg export … > <file> - dump header and diff between one or more changesets
hg import <file> - import changes. Alias: patch
$ hg log
...
$ hg export -r 5:7 > changes.diff
### Other developer
$ hg clone uthg integration
$ cd integration
$ hg import changes.diff
### test if there are no issues, then
$ cd ../uthg
$ hg pull ../integration
Sharing changes - shared repoUsing shared repo is very similar to one-local-repo-per- feature workflow
The only differences:
● repo is in internet● local repos are user
repos, not feature repos
$ hg clone https://[email protected]/tooms/uthg
...
Sharing changes - shared repoSetup once:
1. create repo over web2. give access to devs
Then each dev:
3. clones the repo4. push and pull regularly
$ hg clone https://[email protected]/tooms/uthg
...
$ hg pull
...
$ hg merge
...
$ hg push
...
Sharing changes - shared repo
How we use Mercurial at Interactive FateOne 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 filesPhotoshop 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 failuresOne 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 tags2 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 changesUnity 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
SummaryBy 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?