Date post: | 27-Jun-2015 |
Category: |
Technology |
Upload: | realnitro |
View: | 514 times |
Download: | 0 times |
MercurialFor devs...
What will we talk about?
● The .hgrc● A Stack of Patches● Basic Commands● Branching, pushing, pulling● Howtos
Assumptions
● You have some programming knowledge● You know the basics of some version control
system○ git○ svn○ cvs○ mercurial○ ...
.hgrc!
Who has no.hgrc?
.hgrc!
Why .hgrc?
● Username● Extensions● Aliases● Other settings● Example:
○ http://confluence.incubaid.com/display/ENG/Incubaid+Starter+Kit
What is .hgrc
● Configuration for your Mercurial● INI file format
○ # Comments○ [sections]○ key = value
.hgrc: Extensions
● Mercurial without extensions is barely useable
● Small core, but easy to extend● Extensions add some sugar● Python scripts
○ Write your own!
.hgrc: Extensions
[extensions]pager = # pipe through less automaticallycolor = # Color outputgraphlog = # ASCII art graphical logsfetch = # Pull-and-merge, use with caremq = # Strip, flexible commit queueshighlight = # syntax highlighting in hgweb
.hgrc: aliases
[alias]blame = annotate -uout-diff = out -pvMin-diff = in -pvM# Show the diff of a given changeset IDshow = log -p -v -r
How to think about Mercurial
It's a stack of patcheswith downward links between them
A Stack of Patches@ 4:ch4ch4: Change number 3Parent: ch3ch3tag: tip
3:ch3ch3: Merge in Alice's workParent: ch2ch2Parent: al1al1
2:ch2ch2: Change number 2Parent: ch1ch1
1:al1al1: Alice's changesparent: ch1ch1
0:ch1ch1: Change number 1Parent: ch0ch0
Patch S
ave Time
Working directory commit
Root commitIdentifies a repository
Stack indexClone-dependent!
Node IDUnique!
Top of the stack
is-child-of
What is a commit?
● Diff● Metadata
○ timestamp○ user○ branch?○ parent(s): 1 or 2○ ...
● If you change any of these fields:○ commit ID will change○ you create a different commit!
SHA1 Unique Commit ID
Cause of all those merges
1:ch2ch2: Change number 2Parent: ch1ch1
0:ch1ch1: Change number 1
Local repository status:
Cause of all those merges
Pull from Alice's repository:
1:ch2ch2: Change number 2Parent: ch1ch1
2:al1al1: Alice's changesparent: ch1ch1
0:ch1ch1: Change number 1
No re-ordering can happen without altering the tags and therefore the unique hashes of the commits!
Cause of all those merges2 'heads'!
1:ch2ch2: Change number 2Parent: ch1ch1
2:al1al1: Alice's changesparent: ch1ch1
0:ch1ch1: Change number 1
We want one 'head'!
Cause of all those merges
1:ch2ch2: Change number 2Parent: ch1ch1
2:al1al1: Alice's changesparent: ch1ch1
0:ch1ch1: Change number 1
-> We need to merge. :-(
3:ch3ch3: Merge in Alice's workParent: ch2ch2Parent: al1al1
Quiz 1
● What is .hgrc good for?
Quiz 1
● What is .hgrc good for?○ Username○ Extensions○ Aliases○ Much, much more
Quiz 1
● What is .hgrc good for?○ Username○ Extensions○ Aliases○ Much, much more
● How should you imagine a Mercurial repository?
Quiz 1
● What is .hgrc good for?○ Username○ Extensions○ Aliases○ Much, much more
● How should you imagine a Mercurial repository?○ As a stack of patches.
Basic Commands
● help● clone● init● add/remove/addremove● cp/rename/mv● status● diff● commit
Help!
● hg help: General help○ List of commands○ List of extensions○ Additional help topics (advanced stuff)
● hg help <command>○ hg <command> --help
Cloning a repository
● hg clone <remote> <foldername>● Creates a .hg folder in <foldername>● Downloads all the patches/commits from
<remote>● Checks out the files of the last commit on the
default branch on your disk, in <foldername>
Init: Creating a new repository
● hg init <foldername>● Creates a .hg folder in <foldername>
○ No commits yet○ No changes yet
Add/Remove/Addremove
● hg add <path>○ 'enables' <path> for committing
● hg rm <path>○ 'disables' <path> for committing
● hg addremove <path>○ "Add all new files and remove all missing files from
the repository."○ Use with care (.hgignore!)
● Paths either absolute or relative to $PWD!○ <> 'hg status' output
cp/rename/mv/move
● Avoid having to add/rm● hg cp● hg rename
○ Aliases: mv, move
Status
● Show which files are:○ Added (A)○ Removed (R)○ Modified (M)○ Missing (!) - use hg rm○ Not tracked (?) - use hg add
● Paths relative to repository root (annoying)○ Try hg status .○ Mercurial 1.7 or higher:
■ Alias: stat = !hg status $($HG root) $HG_ARGS
.hgignore
● Tell Mercurial to ignore files in your repository○ mycode.pyc○ README.txt~○ mycode.py.orig○ mycode.py.rej○ ...
● 2 ways of matching○ Regex (default)
■ .pyc$ or re:.pyc$○ glob (~bash)
■ glob:**.pyc● Located in `hg root`
.hgignore: Example
syntax: globdoc/*.auxdoc/_build/htmldist/*arakoon.native**.pycsyntax:regexp^_build~$
locate: test a pattern
● "locate files matching specific patterns"● hg locate "glob:**.py"
○ The quotes are needed to avoid your shell expanding the '*'
● Only prints files under Mercurial control○ Like find, but limited to 'tracked' files.
Diff: what did I change?
● hg diff● Changed files:
○ Show diff with previously committed version● Added files:
○ Show content● Removed files:
○ Show content● Specify <path>
○ Diff only that file/those files○ Can use re: and glob:
● USE COLOR !!!
Color extension
● .hgrc● [extensions]
color =● Colors can be customized● Adds color to almost all commands that have output
○ status○ diff○ log○ ...
Commit: Create a new commit
● hg commit○ Username
■ from .hgrc (preferably!)■ -u "Joske Vermeulen <[email protected]>"
○ Commit message■ in editor (default)■ -m "My commit"
○ Files■ Default: everything shown as A/R/M in status■ Use -I and -X for more control (re, glob)
● Creates a new commit● Use nice commit messages
Log: check the history
● hg log● Order: stack of patches!● Spammy? There's an extension for that!
[extensions]pager =
[pager] pager = less -R attend = annotate, cat, df, diff, >>glog, help, in-diff, incoming, >>log, out-diff, outgoing, qdiff,>>show, tip, grep
Graph log
● Useful when branching, merging, ...● ASCII art graphs!● Need to enable the extension
○ [extensions]graphlog =
● hg glog● @ marks the working directory commit
Example glog output:| o changeset: 3246:1f56e1265e40
| |\ parent: 3245:96b848f10790
| | | parent: 3243:72b775711468
| | | user: Mohammed Azmy <[email protected]>
| | | date: Thu Sep 13 10:36:17 2012 +0200
| | | summary: Automatic merge
| | |
| | @ changeset: 3245:96b848f10790
| | | parent: 3236:c544f3aa38cc
| | | user: Mohammed Azmy <[email protected]>
| | | date: Thu Sep 13 10:35:49 2012 +0200
| | | summary: return empty string if key is none
| | |
o | | changeset: 3244:ed5095ad82a8
|/ / user: Jens Geiregat <[email protected]>
Quiz 2: basic hg commands
● Start tracking an untracked file?
Quiz 2: basic hg commands
● Start tracking an untracked file?○ hg add <path>
Quiz 2: basic hg commands
● Start tracking an untracked file?○ hg add <path>
● Print the root of the repository you're in?
Quiz 2: basic hg commands
● Start tracking an untracked file?○ hg add <path>
● Print the root of the repository you're in?○ hg root
Quiz 2: basic hg commands
● Start tracking an untracked file?○ hg add <path>
● Print the root of the repository you're in?○ hg root
● Commit only one file when multiple are changed?
Quiz 2: basic hg commands
● Start tracking an untracked file?○ hg add <path>
● Print the root of the repository you're in?○ hg root
● Commit only one file when multiple are changed?○ hg commit -I <path>
Quiz 2: basic hg commands
● Start tracking an untracked file?○ hg add <path>
● Print the root of the repository you're in?○ hg root
● Commit only one file when multiple are changed?○ hg commit -I <path>
● Command to show an ASCII art log graph?
Quiz 2: basic hg commands
● Start tracking an untracked file?○ hg add <path>
● Print the root of the repository you're in?○ hg root
● Commit only one file when multiple are changed?○ hg commit -I <path>
● Command to show an ASCII art log graph?○ hg glog
Quiz 2: basic hg commands
● Start tracking an untracked file?○ hg add <path>
● Print the root of the repository you're in?○ hg root
● Commit only one file when multiple are changed?○ hg commit -I <path>
● Command to show an ASCII art log graph?○ hg glog
● Mark for the working directory commit?
Quiz 2: basic hg commands
● Start tracking an untracked file?○ hg add <path>
● Print the root of the repository you're in?○ hg root
● Commit only one file when multiple are changed?○ hg commit -I <path>
● Command to show an ASCII art log graph?○ hg glog
● Mark for the working directory commit?○ @
Branching, pushing, pulling
● branch● update● identify● push● pull● incoming, outgoing
Branching...
● Not very flexible in Mercurial○ Unique branch names○ No branch renames○ Branch name must be chosen before first commit on
that branch○ ...
● Just adds a "branch=name" to the metadata of a commit.
● Default branch has no "branch=default"● Interesting comparison: http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/
4:ch3ch3: Change number 3Parent: ch2ch2
Patch S
ave Time
Back to the stack of patches...
5:ch4ch4: Change number 4Parent: ch3ch3
6:cb1cb1: Branching!Parent: ch3ch3branch: mybranch
7:ch5ch5: Change number 5Parent: ch4ch4
8:cb2cb2: Also on the branchParent: cb1cb1branch: mybranchtag: tip
hg update 4 && hg branch mybranch
hg update default
hg update mybranch
Branch-related commands
● hg branch○ What branch am I on?
● hg branches○ What branches are there?
● hg branch <name>○ Create a branch with <name>
Update
● Changes the working directory commit (@)○ hg update <branchname>
■ Go to the last commit on branch <branchname>○ hg update <rev>
■ Go to revision <rev>● Discard local changes (danger, no backup!)
○ hg update --clean ...○ Forces the update
Identify
● Prints the working directory commit (@)● hg identify
c640c961a243 tip
Push
● Send changesets not yet at <remote> to <remote>
● hg push○ Push to 'default'
● hg push ssh://[email protected]/incubaid/pylabs-core-5.1
○ Explicit target● hg push default
○ Push to 'default' path explicitly.○ Define 'default' (and others) in .hg/hgrc
● Protocol: SSH or HTTP (or local)
Push: 'shortcuts'
.hg/hgrc:[paths]default = ssh://[email protected]/incubaid/pylabs-core-5.1private = ssh://[email protected]/geiregaj/pylabs-core-5.1-jens
hg paths
● Prints the named paths for the repository:○ $ hg paths
default = ssh://[email protected]/incubaid/pylabs-core-5.1private = ssh://[email protected]/geiregaj/pylabs-core-5.1-jens
Push -b
● hg push -b default ssh://...● Push one branch
○ Keeps the <remote> clean○ Push your branch to a private repository, after merge
push to the common repository
hg duw
● [alias]duw = push -r .
● Pushes your working directory commit (@)
Pull
● hg pull● hg pull default● hg pull ssh://[email protected]/incubaid/pylabs-core-5.1
● Downloads the changesets that are on <remote> but not on <local>
● Shortcut: hg pull -u○ == hg pull && hg update
● Tip will be the newest of the pulled commits
Incoming, outgoing
● Show commits that would be pulled or pushed
● Useful as a quick check without the danger of pulling things you don't want yet.
Quiz 3
● Why do you need to commit to create a branch?
Quiz 3
● Why do you need to commit to create a branch?○ Because branches only really exist in the commits,
as a tag. No commit means no tag. No tag means no branch.
Quiz 3
● Why do you need to commit to create a branch?○ Because branches only really exist in the commits,
as metadata. No commit means no metadata. No metadata means no branch.
● How to print all branch names?
Quiz 3
● Why do you need to commit to create a branch?○ Because branches only really exist in the commits,
as metadata. No commit means no metadata. No metadata means no branch.
● How to print all branch names?○ hg branches
Quiz 3
● Why do you need to commit to create a branch?○ Because branches only really exist in the commits,
as metadata. No commit means no metadata. No metadata means no branch.
● How to print all branch names?○ hg branches
● How to find out what your working directory commit is?
Quiz 3
● Why do you need to commit to create a branch?○ Because branches only really exist in the commits,
as metadata. No commit means no metadata. No metadata means no branch.
● How to print all branch names?○ hg branches
● How to find out what your working directory commit is?○ hg identify○ hg glog and search for the '@'
Howto's
● Merge● Discard changes● Collaborate● Feature branches● Commit message template● (Bitbucket) SSH keys● Remove a commit● Undo a commit
How to Merge
● This is where things typically go wrong.○ Merge direction...○ > 2 heads○ Conflicts (oh noes!)
Merge Direction: Goal
● A small diff!○ Keeps your tools from choking on HUGE diffs
● From hg merge --help○ The current working directory is updated with all
changes made in the requested revision since the last common predecessor revision.
Merge Direction
1. Create your local commit2. Pull in the latest changes from <remote>3. Check the situation with
a. hg glogb. hg heads
4. Decide on the merge direction5. hg update <base> (if needed)6. hg merge7. Check the merge (tests?)8. Commit
Merge Direction
4:ch3ch3: Change number 3Parent: ch2ch2
5:ch4ch4: Change number 4Parent: ch3ch3
@ 6:abcabc: My changeParent: ch2ch2
7:ch5ch5: Change number 5Parent: ch4ch4
8:ch6ch6: Change number 6Parent: ch5ch5
9:ch7ch7: Change number 7Parent: ch6ch6
Pulled
Merge Direction
4:ch3ch3: Change number 3Parent: ch2ch2
5:ch4ch4: Change number 4Parent: ch3ch3
@ 6:abcabc: My changeParent: ch2ch2
7:ch5ch5: Change number 5Parent: ch4ch4
8:ch6ch6: Change number 6Parent: ch5ch5
@ 9:ch7ch7: Change number 7Parent: ch6ch6
Pulled
hg update ch7ch7
1000 changes
10 changes
Merge Direction
4:ch3ch3: Change number 3Parent: ch2ch2
5:ch4ch4: Change number 4Parent: ch3ch3
6:abcabc: My changeParent: ch2ch2
7:ch5ch5: Change number 5Parent: ch4ch4
8:ch6ch6: Change number 6Parent: ch5ch5
9:ch7ch7: Change number 7Parent: ch6ch6
Pulled
@ 9:ch8ch8c: MergeParent: ch7ch7Parent: abcabc
hg mergehg commit \ -m "Merge"
Merge: > 2 heads
● Mercurial can only merge 2 heads / commit● To merge > 2 heads, merge multiple times
○ Choose head with most changes (biggest diff)○ hg update <bighead>○ hg merge <smallerhead>○ hg commit○ -> repeat
Merge: conflicts
● kdiff3○ 3-way merge tool○ Powerful○ Simple to use○ Install it and configure it in your .hgrc
■ or use my example config...
Merge: conflicts
● Kdiff3!
Result: Edit by clicking A/B/C or by manually editing the text
Common ancestor LocalRemote
Choose line
Next unmerged conflict
Merge: conflicts
● Kdiff3 workflow:○ Fix all unmerged conflicts
■ use triple arrows to find them■ A/B/C or manual edit
○ When all unmerged conflicts are resolved■ Click 'save'■ Exit kdiff3
Howto: discard changes
● You changed or removed a file● But want to restore it to how it looked in the
last commit○ hg revert <path>
● Shortcut: revert everything:○ hg revert --all
● The content before the revert is saved with suffix .orig
● Revert to a specific revision○ hg revert -r abcabc <path>
Howto: Collaborate
● Avoid working on the same files at the same time○ Same for moving files that other people are working
on● Push your code often
○ What if you lose your laptop?○ If you don't want to push to the main repository,
create a private clone on Bitbucket● Merge with care● But...
○ what if Bitbucket goes down?!
Howto: Collaborate
Howto: Collaborate
● hg serve to the rescue!● Runs an HTTP server
○ Browse your repository■ Useful for quick reviews!
○ Pull code from it■ hg pull http://my.ip.com:8000/
● hg serve is built-in
Howto: Collaborate
● Default push/pull 'protocol': SSH● Allows pushing (hg serve does not, by
default)● hg push ssh://user@host/home/user/repo/path/
○ Use SSH keys
Howto: Feature Branches
● Upside:○ Develop your feature without messing up the
'default' branch of the repository● Downside
○ amount of branches might become very large...■ Close your feature branches■ Use clones, bookmarks, ...
Howto: Feature Branches
D0
D1
D2 B1
B2
B3
B4
Default
Feature branch
D3
D4
B5D5
D6
Use --close-branch
Feature merged into defaultNo choice about merge direction here.
Merge latest defaulthg merge default
Howto: commit message template
● .hgrc:○ [ui]
username = Jens Geiregat <...>editor = /usr/bin/vim -c "r ~/.hgtemplate"
○ vim 'command' r[ead] <path>● .hgtemplate:
○ """
Reference:
Signed-off-by:"""
Howto: (Bitbucket) SSH keys
● Easier pushing and pulling from Bitbucket● Easy to set up
○ http://bit.ly/S4l1ly● Invest 2 minutes, gain years of easier
Bitbucket interaction.● Also useful for non-Bitbucket servers
○ Use ssh-copy-id to publish your public key to a remote machine
Howto: Remove a commit
● Removes a commit and every commit depending on it○ DANGER!○ Creates a backup in .hg/strip-backup as a bundle○ Can only be used when the strip happens on ALL
clones that contain the stripped commit(s).● Part of the mq extension:
○ [extensions]mq =
● Bitbucket can strip too○ Part of the admin interface
Howto: undo a commit
● Commit the inverted patch of a previous commit
● hg backout <rev>
Quiz 4
● What is the command to discard changes?
Quiz 4
● What is the command to discard changes?○ hg revert
Quiz 4
● What is the command to discard changes?○ hg revert
● What 'protocols' can be used for push/pull?
Quiz 4
● What is the command to discard changes?○ hg revert
● What 'protocols' can be used for push/pull?○ SSH and HTTP
Quiz 4
● What is the command to discard changes?○ hg revert
● What 'protocols' can be used for push/pull?○ SSH and HTTP
● Which head should you merge to?
Quiz 4
● What is the command to discard changes?○ hg revert
● What 'protocols' can be used for push/pull?○ SSH and HTTP
● Which head should you merge to?○ The one with the most changes
End of the basics.
● But there's much, much more.○ 'Advanced' commands (cat, archive, locate, grep)○ revsets○ mq○ (let me know what you would like to know)○ Anyone interested?
● Links:○ http://confluence.incubaid.
com/display/ENG/Incubaid+Starter+Kit○ http://confluence.incubaid.
com/display/ENG/Mercurial+Cheat+Sheet+-+Hg+Cheat+Sheet
○ http://hginit.com/○ http://hgbook.red-bean.com/
Thank you!
● Questions?
Advanced
● hg cat● hg archive● hg bisect● hg copy ?● hg grep● hg locate
● hg recover● hg resolve ?● hg revert● hg rollback● ext: record