Mercurial intro

Post on 27-Jun-2015

516 views 0 download

Tags:

Transcript of Mercurial intro

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

Minimal .hgrc: Username

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

.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 <joske@incubaid.com>"

○ 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 <mazmy@aserver.com>

| | | date: Thu Sep 13 10:36:17 2012 +0200

| | | summary: Automatic merge

| | |

| | @ changeset: 3245:96b848f10790

| | | parent: 3236:c544f3aa38cc

| | | user: Mohammed Azmy <mazmy@aserver.com>

| | | date: Thu Sep 13 10:35:49 2012 +0200

| | | summary: return empty string if key is none

| | |

o | | changeset: 3244:ed5095ad82a8

|/ / user: Jens Geiregat <jens.geiregat@incubaid.com>

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://hg@bitbucket.org/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://hg@bitbucket.org/incubaid/pylabs-core-5.1private = ssh://hg@bitbucket.org/geiregaj/pylabs-core-5.1-jens

hg paths

● Prints the named paths for the repository:○ $ hg paths

default = ssh://hg@bitbucket.org/incubaid/pylabs-core-5.1private = ssh://hg@bitbucket.org/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://hg@bitbucket.org/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