<<

Mercurial Tutorial

Mark Gates Nov 2016

1 Outline • Basic commands in single repository • Creating repo • Add & edit files • Viewing history • Fixing last • Multiple users / branches • Simple case • without conflicts • Merge with conflicts • Bookmarks • Branches • • Fork • Pull requests • Final thoughts

2 Overview of • Distributed source control management • Each user has copy of entire repository hg • Commits go to local repo Chris Julia • Push & pull between repos • Similar to

! server master server • We use central repo on BitBucket to synchronize • Nothing special about BitBucket repo! svn ! Chris Julia • Unlike svn, where all commits

go to server svn server

3 Help! • Extensive help • hg # basic commands • hg help [-v] # all commands • hg help command [-v] # specific command

>> hg Mercurial Distributed SCM >> hg help ! Mercurial Distributed SCM basic commands: ! >> hg help add ! hg add [OPTION]... [FILE]... list of commands: ! >> hg --version add add the specified files on the next commit ! Mercurial Distributed SCM (version 3.9.2) annotate show information by line for each file add the specified files on the next commit add add the specified files on the next commit ! (see https://mercurial-scm.org for more information) clone make a copy of an existing repository addremove add all new files, delete all missing files ! commit commit the specified files or all outstanding changes Schedule files to be version controlled and added to the repository. annotate show changeset information by line for each file ! ! diff repository (or selected files) archive create an unversioned archive of a repository revision The files will be added to the repository at the next commit. To undo an ! export dump the header and diffs for one or more backout reverse effect of earlier changeset ! forget forget the specified files on the next commit add before that, see 'hg forget'. bisect subdivision search of changesets ! ! init create a new repository in the given directory bookmarks create a new bookmark or list existing bookmarks ! ... options ([+] can be repeated): branch set or show the current branch name ! ! ! branches list repository named branches -I --include PATTERN [+] include names matching the given patterns ! (use "hg help" for the full list of commands or "hg -v" for details) bundle create a changegroup file -X --exclude PATTERN [+] exclude names matching the given patterns ! cat output the current or given revision of files -n --dry-run do not perform actions, just print output ! ... ! ! ! (some details hidden, use --verbose to show complete help)!

4 * throughout, output is abbreviated to fit on slides Configuration ~/.hgrc [ui] ignore = ~/.hgignore • User: ~/.hgrc ! ~/.hgignore [extensions] syntax: glob hgext.extdiff = ! • color = # latex output files Repo: .hg/hgrc shelve = *.aux ! *.bbl [extdiff] *.blg • Suggested items cmd.opendiff = fmdiff *.fff ! *.idx • ~/.hgignore hides files in [diff] *.log git = True *.marks hg status output ! *.nav # https://www.mercurial-scm.org/wiki/ColorExtension *.out • external diff (e.g., graphical) [color] *.snm status.ignored = black *.synctex.gz • git diff output nicer when status.modified = bold blue *.toc status.added = bold green ! renaming files status.removed = bold magenta # compiled files status.deleted = bold red *.a • status.unknown = black *.d color extension colors diff ! *.o diff.tab = red_background *.pyc and status output diff.trailingwhitespace = red_background*.so ! ! • shelve saves changes [alias] # hg backup files glog = log -G *.orig temporarily slog = log --template=short ! # misc files • alias to shorten commands .DS_Store

5 Creating repo

! • hg init [directory] • Creates repo directory (if needed) and .hg directory • By default uses current “.” directory

home> hg init recipes home> cd recipes/ recipes> ls -a ./ ../ .hg/

6 Adding files • hg add [files] • hg status [-acm] [-q] # hg st • -a added • - clean pizza.txt Dough • -m modified 1 1/2 cups warm water (105 °F–115 °F) 1 package active dry yeast • -q quiet (hide unknown files) 3 1/2 cups bread flour 2 Tbsp olive oil 2 tsp salt • hg commit [-m “message”] 1 tsp sugar ! Toppings recipes> jedit pizza.txt 2/3 cup tomato sauce recipes> hg add pizza.txt 2/3 cup mozzarella cheese, grated recipes> hg st ! A pizza.txt # A = added Mix dough ingredients; knead for 10 minutes. ! Cover; rise until double, about 1–1 1/2 hours. recipes> hg commit -m 'start pizza’ Divide dough in half; roll out to 10–12 inches diameter. Spread with tomato sauce & sprinkle with toppings. Bake each at 450 °F for 10–15 minutes until golden.

7 Editing files • hg diff [files]

recipes> jedit pizza.txt pizza.txt recipes> hg st M pizza.txt # M = modified Dough ! 1.5 cups warm water (105 °F–115 °F) recipes> hg diff 1 package active dry yeast diff -r 9ab04aa4c434 pizza.txt 3.5 cups bread flour --- a/pizza.txt Tue Oct 25 07:58:39 2016 -0400 2 Tbsp olive oil +++ b/pizza.txt Tue Oct 25 08:03:53 2016 -0400 2 tsp salt @@ -1,7 +1,7 @@ 1 tsp sugar Dough ! -1 1/2 cups warm water (105 °F–115 °F) Toppings +1.5 cups warm water (105 °F–115 °F) 2/3 cup tomato sauce 1 package active dry yeast 2/3 cup mozzarella cheese, grated -3 1/2 cups bread flour +3.5 cups bread flour ! 2 Tbsp olive oil Mix dough ingredients; knead for 10 minutes. 2 tsp salt Cover; rise until double, about 1–1 1/2 hours. 1 tsp sugar Divide dough in half; roll out to 10–12 inches diameter. ! Spread with tomato sauce & sprinkle with toppings. recipes> hg commit -m 'use decimal' Bake each at 450 °F for 10–15 minutes until golden.

8 pizza.txt

History Dough 1.5 cups warm water (105 °F–115 °F) 1 package active dry yeast • hg diff -r revision 3.5 cups bread flour 2 Tbsp olive oil • Working files compared to that revision 2 tsp salt 1 tsp sugar ! • hg diff -c revision Toppings 2/3 cup tomato sauce • Changes that occurred in that revision 2/3 cup mozzarella cheese, grated 1/3 cup feta cheese, crumbled ! Mix dough ingredients; knead for 10 minutes. Cover; rise until double, about 1–1 1/2 hours. Divide dough in half; roll out to 10–12 inches recipes> hg diff -c 1 diameter. diff -r 9ab04aa4c434 -r 0b85839d8a57 pizza.txt Spread with tomato sauce & sprinkle with --- a/pizza.txt Tue Oct 25 07:58:39 2016 -0400 +++ b/pizza.txt Tue Oct 25 08:05:45 2016 -0400 @@ -1,7 +1,7 @@ recipes> hg diff Dough # or -1 1/2 cups warm water (105 °F–115 °F) recipes> hg diff -r 1 +1.5 cups warm water (105 °F–115 °F) diff -r 0b85839d8a57 pizza.txt 1 package active dry yeast --- a/pizza.txt Tue Oct 25 08:05:45 2016 -0400 -3 1/2 cups bread flour +++ b/pizza.txt Tue Oct 25 11:42:24 2016 -0400 +3.5 cups bread flour @@ -9,6 +9,7 @@ 2 Tbsp olive oil 2/3 cup tomato sauce 2 tsp salt 2/3 cup mozzarella cheese, grated 1 tsp sugar +1/3 cup feta cheese, crumbled @@ -11,7 +11,7 @@ 2/3 cup mozzarella cheese, grated Mix dough ingredients; knead for 10 minutes.

9 History recipes> hg log changeset: 1:0b85839d8a57 user: [email protected] • hg log [-l num] [-G] [--stat] date: Tue Oct 25 08:05:45 2016 -0400 summary: use decimal • -l limit to last num commits ! changeset: 0:9ab04aa4c434 user: [email protected] • -G graph date: Tue Oct 25 07:58:39 2016 -0400 • --stat show files changed summary: start pizza recipes> hg log --stat changeset: 1:0b85839d8a57 • commits identified 2 ways user: [email protected] date: Tue Oct 25 08:05:45 2016 -0400 • summary: use decimal Local version number ! (0, 1, 2, ...) pizza.txt | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) • ! Local only! Different for changeset: 0:9ab04aa4c434 different users user: [email protected] date: Tue Oct 25 07:58:39 2016 -0400 summary: start pizza • Global unique hash ! pizza.txt | 17 +++++++++++++++++ (e.g., 0b85839d8a57) 1 files changed, 17 insertions(+), 0 deletions(-)

• Terminology: commits == revisions == changesets

10 History • Customizable log templates • hg log --template list # show available templates • Examples

• http://hgtip.com/tips/advanced/2010-01-15-styling-mercurials-cli/ • Custom

recipes> hg log --template=custom 9 5231fa16d647 2016-10-28 13:16 misc mgates3 default 8 b1047ddb7fca 2016-10-28 11:57 grind mgates3 sauce @7 90b0579b4629 2016-10-28 11:57 onion mgates3 sauce [*main] 6 83c38f1e80dd 2016-10-28 11:22 merge sauce mgates3 default 3,5 [saucier] 5 ff3b0aca8e36 2016-10-28 11:21 saute mgates3 sauce (v1.1) 4 f82b641f9506 2016-10-28 11:20 brand mgates3 sauce 3 1119625a9723 2016-10-28 11:20 preheat mgates3 default 2 d82ee94655b3 2016-10-28 11:19 meat mgates3 default (v1.0) 1 49bb5328310f 2016-10-28 11:19 start sauce mgates3 sauce 0 6ec9bb1d6c4c 2016-10-28 11:17 start pizza mgates3 default ! recipes> hg slog # alias in ~/.hgrc

11 Copy, move files • hg cp source destination [-A]

• hg mv source destination [-A] pizza.txt Dough veggie.txt recipes> hg cp pizza.txt veggie.txt 1.5 cups warm water (105 °F–115 °F) recipes> jedit veggie.txt 1 package active dry yeast 3.5 cupsDough bread flour recipes> hg st 1.5 cups warm water (105 °F–115 °F) A veggie.txt 2 Tbsp olive oil 2 tsp salt1 package active dry yeast ! 3.5 cups bread flour recipes> hg diff # git option in ~/.hgrc 1 tsp sugar 2 Tbsp olive oil diff --git a/pizza.txt b/veg.txt ! 2 tsp salt copy from pizza.txt Toppings 1 tsp sugar copy to veggie.txt 2/3 cup tomato sauce --- a/pizza.txt 2/3 cup! mozzarella cheese, grated +++ b/veggie.txt ! Toppings 2/3 cup mozzarella cheese, grated Mix dough2/3 cup ingredients tomato sauce; knead for 10 minutes. +1/2 cup bell peppers, thinly sliced Cover;2/3 rise cup until mozzarella double, about cheese, 1–1.5 grated hours. +1/2 cup chopped fresh basil Divide1/2 dough cup bell in half; peppers, roll out thinly to 10–12 sliced inches diameter. +1/2 cup onions, diced Spread1/2 with cup tomato chopped sauce fresh & basilsprinkle with toppings. ! Bake each1/2 cup at 450onions, °F for diced 10–15 minutes until golden. recipes> hg commit -m 'add veggie' ! Mix dough ingredients; knead for 10 minutes. Cover; rise until double, about 1–1.5 hours. Divide dough in half; roll out to 10–12 inches diameter. Spread with tomato sauce & sprinkle with toppings. Bake each at 450 °F for 10–15 minutes until golden.

12 Copy, move files • hg cp source destination [-A]

• hg mv source destination [-A] pizza.txt Dough veggie.txt recipes> hg mv pizza.txt veggie.txt 1.5 cups warm water (105 °F–115 °F) recipes> 1 package active dry yeast hg st Dough A veggie.txt # A = added 3.5 cups bread flour 1.5 cups warm water (105 °F–115 °F) R pizza.txt # R = removed 2 Tbsp olive oil 1 package active dry yeast recipes> hg commit -m 'rename to veggie' 2 tsp salt 1 tsp sugar3.5 cups bread flour 2 Tbsp olive oil recipes> mv pizza.txt veggie.txt ! Toppings2 tsp salt recipes> hg st 1 tsp sugar ! pizza.txt # ! = tracked file missing 2/3 cup! tomato sauce ? veggie.txt # ? = untracked file 2/3 cup mozzarella cheese, grated Toppings recipes> ! hg mv pizza.txt veggie.txt -A 2/3 cup tomato sauce recipes> hg st Mix dough ingredients; knead for 10 minutes. Cover;2/3 rise cup until mozzarella double, about cheese, 1–1.5 grated hours. A veggie.txt 1/2 cup bell peppers, thinly sliced R pizza.txt Divide dough in half; roll out to 10–12 inches diameter. 1/2 cup chopped fresh basil recipes> Spread with tomato sauce & sprinkle with toppings. hg commit -m 'rename to veggie' 1/2 cup onions, diced Bake each! at 450 °F for 10–15 minutes until golden. Mix dough ingredients; knead for 10 minutes. Cover; rise until double, about 1–1.5 hours. Divide dough in half; roll out to 10–12 inches diameter. Spread with tomato sauce & sprinkle with toppings. Bake each at 450 °F for 10–15 minutes until golden.

13 Remove files • hg rm files [-f] [-A]

pizza.txt

recipes> hg rm veggie.txt Dough veggie.txt recipes> hg st 1.5 cups warm water (105 °F–115 °F) R veggie.txt 1 package active dry yeast recipes> hg commit -m 'remove veggie' 3.5 cupsDough bread flour 2 Tbsp1.5 olive cups oil warm water (105 °F–115 °F) recipes> rm veggie.txt 2 tsp salt1 package active dry yeast recipes> hg st 1 tsp sugar3.5 cups bread flour ! veggie.txt ! 2 Tbsp olive oil recipes> hg rm veggie.txt [-A] Toppings2 tsp salt recipes> hg st 2/3 cup1 tsp tomato sugar sauce R veggie.txt 2/3 cup! mozzarella cheese, grated recipes> hg commit -m 'remove veggie' ! Toppings Mix dough2/3 cup ingredients tomato sauce; knead for 10 minutes. recipes> jedit veggie.txt Cover;2/3 rise cup until mozzarella double, about cheese, 1–1.5 grated hours. recipes> hg st Divide1/2 dough cup bellin half; peppers, roll out thinly to 10–12 sliced inches diameter. M veggie.txt Spread1/2 with cup tomato chopped sauce fresh & sprinklebasil with toppings. recipes> hg rm veggie.txt Bake each1/2 cup at 450 onions, °F for diced 10–15 minutes until golden. not removing veggie.txt: file is modified (use -f to force removal) ! recipes> hg rm veggie.txt -f Mix dough ingredients; knead for 10 minutes. recipes> hg st Cover; rise until double, about 1–1.5 hours. R veggie.txt Divide dough in half; roll out to 10–12 inches diameter. recipes> hg commit -m 'remove veggie' Spread with tomato sauce & sprinkle with toppings. Bake each at 450 °F for 10–15 minutes until golden.

14 Reverting changes veggie.txt • hg revert files Dough 1.5 cups warmsupreme.txt water (105 °F–115 °F) recipes> hg cp pizza.txt supreme.txt 1 package active dry yeast recipes> Dough 3.5 cups bread flour hg rm veggie.txt pizza.txt recipes> jedit pizza.txt 1.5 cups warm2 Tbsp water olive (105 oil °F–115 °F) recipes> hg st 1 package active2 tsp salt dry yeast TeigDough M pizza.txt 3.5 cups bread1 tsp flour sugar 1,51.5 Tassencups warm warmes water Wasser (105 °F–115 (105 ° F-115°F) ° F) A supreme.txt 2 Tbsp olive! oil 1 Packungpackage activeaktive dry Trockenhefe yeast R veggie.txt 2 tsp salt Toppings ! 1 tsp3,53.5 sugar Tassencups2/3 bread cupBrotmehl tomatoflour sauce 2 ELTbsp Olivenöl olive oil recipes> hg revert pizza.txt ! 2/3 cup mozzarella cheese, grated 2 TLtsp Salzsalt recipes> hg st Toppings 1/2 cup bell peppers, thinly sliced 1 TLtsp Zuckersugar A supreme.txt 2/3 cup tomato1/2 cup sauce chopped fresh basil R veggie.txt 2/3 cup! mozzarella1/2 cup onions, cheese, diced grated ! italianToppings sausage,! cooked recipes> hg revert . # “.” directory mushrooms,2/3 TassecupMix thinlytomato Tomatensoße dough sliced sauce ingredients; knead for 10 minutes. forgetting supreme.txt bell peppers,2/3 TassecupCover; mozzarellathinly Mozzarella, rise sliced until cheese, geriebendouble, grated about 1–1.5 hours. undeleting veggie.txt chopped! freshDivide basil dough in half; roll out to 10–12 inches diameter. ! pestoMix TeigdoughSpread Zutaten; ingredients with 10 tomato Minuten; knead sauce kneten.for & 10 sprinkle minutes. with toppings. recipes> hg st pepporoniAbdeckung;Cover; Bake rise untileach Steigen atdouble, 450 bis °F doppelt, about for 10–15 1–1.5 ca. minutes 1-1,5hours. Stunden. until golden. ? supreme.txt onions,TeigDivide diced in derdough Hälfte in half; teilen; roll Roll-out out to 10–12 bis 10-12 inches Zoll diameter. Durchmesser. ! ham,MitSpread diced Tomatensauce with tomato bestreichen sauce & sprinkle und mit with Toppings toppings. bestreuen. recipes> ls -1 ! BackenBake each Sie at jeweils 450 °F bei for 450 10–15 ° F minutesfür 10-15 until Minuten, golden. bis golden. pizza.txt Mix dough ingredients; knead for 10 minutes. pizza.txt.orig # backup Cover; rise until double, about 1–1.5 hours. supreme.txt # backup Divide dough in half; roll out to 10–12 inches diameter. veggie.txt Spread with tomato sauce & sprinkle with toppings. Bake each at 450 °F for 10–15 minutes until golden.

15 Fixing last commit (only last!)

• hg rollback pizza.txt Dough recipes> jedit veggie.txt 1.5 cups warm H20 (105 °F–115 °F) recipes> jedit pizza.txt 1 package active dry yeast recipes> 3.5 cups bread flour hg st veggie.txt M pizza.txt 2 Tbsp olive oil M veggie.txt 2 tsp salt Dough recipes> hg commit -m 'H20' 1 tsp sugar 1.5 cups warm H20 (105 °F–115 °F) recipes> hg log -l 2 ! 1 package active dry yeast changeset: 5:22456188656d Toppings 3.5 cups bread flour tag: tip 2/3 cup tomato sauce 2 Tbsp olive oil summary: H20 2/3 cup mozzarella cheese, grated ! ! 2 tsp salt changeset: 4:7a81b46fbf59 Mix dough1 tsp sugar ingredients ; knead for 10 minutes. summary: rename to veggie Cover;! rise until double, about 1–1.5 hours. ! DivideToppings dough in half; roll out to 10–12 inches diameter. recipes> hg rollback Spread2/3 with cup tomatotomato saucesauce & sprinkle with toppings. repository tip rolled back to revision 4 (undo commit) Bake2/3 each cup at 450mozzarella °F for 10–15 cheese, minutes grated until golden. working directory now based on revision 4 1/2 cup bell peppers, thinly sliced ! 1/2 cup chopped fresh basil recipes> hg log -l 2 1/2 cup onions, diced changeset: 4:7a81b46fbf59 ! tag: tip Mix dough ingredients; knead for 10 minutes. summary: rename to veggie Cover; rise until double, about 1–1.5 hours. ! Divide dough in half; roll out to 10–12 inches diameter. recipes> hg st Spread with tomato sauce & sprinkle with toppings. M pizza.txt Bake each at 450 °F for 10–15 minutes until golden. M veggie.txt

16 Fixing last commit (only last!) • hg commit --amend • Destroys rollback information • Changes global hash identifier, but not date • Can change message

recipes> jedit veggie.txt recipes> hg commit --amend veggie.txt recipes> jedit pizza.txt saved backup bundle to /Users/mgates/Documents/ recipes> hg st writing/2016/mercurial/recipes/.hg/strip-backup/ M pizza.txt 167f86be8569-954506e9-amend-backup.hg M veggie.txt ! recipes> hg commit -m 'H20' pizza.txt recipes> hg st recipes> hg st recipes> M veggie.txt ! ! ! recipes> hg log -l 1 --stat recipes> hg log -l 1 --stat changeset: 5:167f86be8569 changeset: 5:65d210f5f675 tag: tip tag: tip date: Tue Oct 25 11:01:21 2016 -0400 date: Tue Oct 25 11:01:21 2016 -0400 summary: H20 summary: H20 ! ! pizza.txt | 2 +- pizza.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) veggie.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)

17 Outline • Basic commands in single repository • Creating repo • Add & edit files • Viewing history • Fixing last commit • Multiple users / branches • Simple case • Merge without conflicts • Merge with conflicts • Bookmarks • Branches • BitBucket • Fork • Pull requests • Final thoughts

18 3 kinds of branches • Forks (or clones) — copies of repo • Every copy is a fork! You cannot avoid branching! • Typically for development; periodically synchronize • Same as git forking • Bookmarks • Typically short-lived for feature development • Same as git’s branches • Named branches • Typically long-lived branches like “stable” and “devel” • Branch name permanently recorded in commit log

19 Simple example — one person editing at a time

20 Basic server interaction • Simple example with only one person editing at a time • hg clone url [directory] Chris Julia

• hg push [url] update commit • hg pull [url] [-u] pull push • hg update # hg up server

Server: 0 1 2 3

clone push pull

Chris: 0: pizza 1: feta 2 3

clone push

Julia: 0 1 2: meat 3: preheat

21 dashed lines are copies solid lines are dependencies Basic server interaction

home> hg clone ssh://server/recipes chris home> cd chris chris> ls -a ./ ../ .hg/

.hg/hgrc

[paths] default = ssh://server/recipes

Server:

clone Chris:

Julia:

22 dashed lines are copies solid lines are dependencies Basic server interaction

home> hg clone ssh://server/recipes chris pizza.txt home> cd chris ! Dough pizza.txt chris> jedit pizza.txt 1 1/2 cups warm water (105 °F–115 °F) chris> hg commit -m ‘start pizza' 1 packageDough active dry yeast chris> jedit pizza.txt 3 1/21 cups 1/2 breadcups warm flour water (105 °F–115 °F) chris> hg commit -m ‘feta' 2 Tbsp1 packageolive oil active dry yeast chris> hg push 2 tsp 3salt 1/2 cups bread flour pushing to ssh://server/recipes 1 tsp 2sugar Tbsp olive oil mercurial/recipes ! 2 tsp salt searching for changes Toppings1 tsp sugar adding changesets 2/3 cup! tomato sauce adding manifests 2/3 cup mozzarella cheese, grated adding file changes ! Toppings added 2 changesets with 2 changes to 1 files 2/3 cup tomato sauce Mix dough2/3 cup ingredients mozzarella; knead cheese, for grated 10 minutes. Cover;1/3 rise cup until feta double, cheese, about crumbled 1–1 1/2 hours. Divide! dough in half; roll out to 10–12 inches diameter. SpreadMix with dough tomato ingredients sauce & ;sprinkle knead for with 10 minutes.toppings. Bake each at 450 °F for 10–15 minutes until golden. Server: 0 1 Cover; rise until double, about 1–1 1/2 hours. Divide dough in half; roll out to 10–12 inches diameter. Spread with tomato sauce & sprinkle with toppings. clone push Bake each at 450 °F for 10–15 minutes until golden. Chris: 0: pizza 1: feta

Julia:

23 dashed lines are copies solid lines are dependencies Basic server interaction

home> hg clone ssh://server/recipes julia pizza.txt home> cd julia ! Dough pizza.txt julia> jedit pizza.txt 1 1/2 cups warm water (105 °F–115 °F) julia> hg commit -m ‘meat' 1 package active dry yeast Dough julia> hg commit -m ‘preheat' 3 1/2 cups bread flour 1 1/2 cups warm water (105 °F–115 °F) julia> hg push 2 Tbsp olive oil 1 package active dry yeast pushing to ssh://server/recipes 2 tsp salt 3 1/2 cups bread flour searching for changes 1 tsp sugar adding changesets ! 2 Tbsp olive oil 2 tsp salt adding manifests Toppings 1 tsp sugar adding file changes 2/3 cup tomato sauce added 2 changesets with 2 changes to 1 files 2/3 cup! mozzarella cheese, grated Toppings 1/3 cup feta cheese, crumbled 2/3 cup tomato sauce 1/2 cup Italian sausage, cooked 2/3 cup mozzarella cheese, grated 1/4 cup pepperoni ! 1/3 cup feta cheese, crumbled 1/2 cup Italian sausage, cooked Mix dough ingredients; knead for 10 minutes. 1/4 cup pepperoni Cover; rise until double, about 1–1 1/2 hours. 0 1 2 3 Server: Divide! dough in half; roll out to 10–12 inches diameter. Mix dough ingredients; knead for 10 minutes. Spread with tomato sauce & sprinkle with toppings. Cover; rise until double, about 1–1 1/2 hours. clone push Bake each at 450 °F for 10–15 minutes until golden. Preheat oven to 450 °F. Chris: 0: pizza 1: feta Divide dough in half; roll out to 10–12 inches diameter. Spread with tomato sauce & sprinkle with toppings. Bake each at 450 °F for 10–15 minutes until golden. clone push

Julia: 0 1 2: meat 3: preheat

24 dashed lines are copies solid lines are dependencies Basic server interaction

chris> hg pull chris> hg pull -u pulling from ssh://server/recipes pulling from ssh://server/recipes searching for changes searching for changes adding changesets adding changesets adding manifests – or – adding manifests adding file changes adding file changes added 2 changesets with 2 changes to 1 files added 2 changesets with 2 changes to 1 files pizza.txt (run 'hg update' to get a working copy) 1 files updated, 0 files merged, 0 files removed, 0 files unresolved Dough pizza.txt Note that working copy not yet updated! 1 1/2 cups warm water (105 °F–115 °F) 1 packageDough active dry yeast 3 1/2 cups bread flour chris> hg up 1 1/2 cups warm water (105 °F–115 °F) 2 Tbsp olive oil 1 files updated, 0 files merged, 0 files 1 package active dry yeast removed, 0 files unresolved 2 tsp salt3 1/2 cups bread flour 1 tsp sugar2 Tbsp olive oil ! 2 tsp salt Toppings1 tsp sugar 2/3 cup! tomato sauce 2/3 cup mozzarella cheese, grated Server: 0 1 Toppings 2 3 1/3 cup2/3 feta cup cheese, tomato crumbled sauce ! 2/3 cup mozzarella cheese, grated clone push pull Mix dough1/3 cup ingredients feta cheese,; knead crumbled for 10 minutes. Cover;1/2 rise cup until Italian double, sausage, about cooked 1–1 1/2 hours. 0: pizza 1: feta 2 3 Chris: Divide1/4 dough cup pepperoni in half; roll out to 10–12 inches diameter. Spread! with tomato sauce & sprinkle with toppings. clone Bake eachMix doughat 450 °F ingredients; forpush 10–15 minutes knead for until 10 minutes.golden. Cover; rise until double, about 1–1 1/2 hours. Julia: 0 1 Preheat2: meat oven to3: 450 preheat °F. Divide dough in half; roll out to 10–12 inches diameter. Spread with tomato sauce & sprinkle with toppings. 25 dashed lines are copies solid lines are dependenciesBake each at 450 °F for 10–15 minutes until golden. Simple merge — two simultaneous edits, without conflicts

26 Merge without conflicts • Merge is required if edits happen in parallel • Local commit numbers differ • hg merge

4: veg Server: 0:3 6: merge 5: ham

push pull

4: veg Chris: 0:3 6: merge 5: ham

push pull push

5: veg Julia: 0:3 6: merge 4: ham

27 dashed lines are copies solid lines are dependencies Merge pizza.txt

Dough chris> jedit pizza.txt pizza.txt chris> hg commit -m ‘veggies' 1 1/2 cups warm water (105 °F–115 °F) 1 package active dry yeast chris> hg push Dough 3 1/2 cups bread flour 1 1/2 cups warm water (105 °F–115 °F) 2 Tbsp olive oil julia> jedit pizza.txt 1 package active dry yeast 2 tsp salt julia> hg commit -m ‘ham' 3 1/2 cups bread flour 1 tsp sugar julia> hg push 2 Tbsp olive oil pushing to ssh://server/recipes ! 2 tsp salt Toppings searching for changes 1 tsp sugar remote has heads on branch 'default' that are not known locally: 7dc71c9ebfc4 2/3 cup! tomato sauce 2/3 cup mozzarella cheese, grated abort: push creates new remote head c7f726f74e9a! Toppings (pull and merge or see "hg help push" for details about pushing new heads)1/3 cup feta cheese, crumbled 2/3 cup tomato sauce 1/4 cup mushrooms, thinly sliced 2/3 cup mozzarella cheese, grated 1/4 cup bell peppers, thinly sliced 1/3 cup feta cheese, crumbled 1/2 cup Italian sausage, cooked 4: veg 1/2 cup Italian sausage, cooked 1/4 cup pepperoni Server: 0:3 1/4 cup pepperoni ! 1/4 cup ham Mix dough! ingredients; knead for 10 minutes. Cover; rise until double, about 1–1 1/2 hours. push Mix dough ingredients; knead for 10 minutes. Preheat oven to 450 °F. Cover; rise until double, about 1–1 1/2 hours. Divide dough in half; roll out to 10–12 inches diameter. 4: veg Preheat oven to 450 °F. 0:3 Chris: Divide dough in half; roll out to 10–12 inches diameter. Spread with tomato sauce & sprinkle with toppings.

push

Julia: 0:3 4: ham

28 dashed lines are copies solid lines are dependencies Merge

julia> hg pull julia> hg merge pulling from ssh://server/recipes merging pizza.txt searching for changes 0 files updated, 1 files merged, 0 files removed, 0 files unresolved adding changesets (branch merge, don't forget to commit) adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge) ! julia> hg up # warning, does nothing 0 files updated, 0 files merged, 0 files removed, 0 files unresolved 1 other heads for branch "default"

4: veg Server: 0:3

push

4: veg Chris: 0:3

push pull

5: veg Julia: 0:3 6: merge 4: ham

29 dashed lines are copies solid lines are dependencies Merge — verify & commit!

julia> hg heads julia> hg diff -r 5 changeset: 5:962db491f9ca @@ -14,7 +14,6 @@ summary: veggies 1/2 cup Italian sausage, cooked ! 1/4 cup pepperoni changeset: 4:b1473e48944e +1/4 cup ham summary: ham ! ! julia> hg commit -m ‘merge' julia> hg diff -r 4 julia> hg push # optional @@ -10,8 +10,6 @@ pushing to ssh://server/recipes 1/3 cup feta cheese, crumbled searching for changes +1/4 cup mushrooms, thinly sliced adding changesets +1/4 cup bell peppers, thinly sliced adding file changes 1/2 cup Italian sausage, cooked added 2 changesets with 2 changes to 1 files

4: veg Server: 0:3 6: merge 5: ham

push

4: veg Chris: 0:3

push pull push

5: veg Julia: 0:3 6: merge 4: ham

30 dashed lines are copies solid lines are dependencies Merge

chris> hg pull pulling from /Users/mgates/Documents/writing/2016/mercurial/recipes searching for changes adding changesets adding manifests adding file changes added 2 changesets with 2 changes to 1 files (run 'hg update' to get a working copy) ! chris> hg up 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

4: veg Server: 0:3 6: merge 5: ham

push pull

4: veg Chris: 0:3 6: merge 5: ham

push pull push

5: veg Julia: 0:3 6: merge 4: ham

31 dashed lines are copies solid lines are dependencies Conflict merge — two simultaneous edits to same text

32 Merge with conflict • Simplify recipe slightly, then add ingredients in same spot

pizza.txt

Dough 1 1/2 cupspizza.txt warm water (105 °F–115 °F) pizza.txt 1 package active dry yeast 3 1/2 cupsDough bread flour Dough 2 Tbsp olive1 1/2 oil cups warm water (105 °F–115 °F) 1 1/2 cups warm water (105 °F–115 °F) 2 tsp salt1 package active dry yeast 1 package active dry yeast 1 tsp sugar3 1/2 cups bread flour 3 1/2 cups bread flour ! 2 Tbsp extra virgin olive oil 2 Tbsp olive oil Toppings2 tsp sea salt 2 tsp salt 2/3 cup1 tomato tsp sugar sauce 1 tsp sugar 2/3 cup! mozzarella cheese, grated ! 1/2 cupToppings Italian sausage, cooked Toppings ! 2/3 cup tomato sauce 2/3 cup tomato sauce Mix dough2/3 ingredients;cup mozzarella knead cheese, for 10 grated minutes. 2/3 cup mozzarella cheese, grated Cover; rise1/2 cupuntil bell double, peppers, about thinly 1–1 1/2 sliced hours. 1/4 cup mushrooms, sliced Preheat 1/3oven cup to mushrooms450 °F. 1/4 cup onions, diced Divide dough1/2 cup in Italian half; roll sausage, out to cooked10–12 inches diameter. 1/2 cup Italian sausage, cooked Spread with! tomato sauce & sprinkle with toppings. ! Bake eachMix at dough450 °F ingredients;for 10–15 minutes knead until for 10 golden. minutes. Mix dough ingredients; knead for 10 minutes. Cover; rise until double, about 1–1 1/2 hours. Cover; rise until double, about 1–1 1/2 hours. Preheat oven to 450 °F. Preheat oven to 450 °F. Divide dough in half; roll out to 10–12 inches diameter. Divide dough in half; spin in air to 10–12 inches diameter. Spread with tomato sauce & sprinkle with toppings. Spread with tomato sauce & sprinkle with toppings. Bake each at 450 °F for 10–15 minutes until golden. Bake each at 450 °F for 10–15 minutes until golden.

33 Merge with conflict: graphical • Graphical diff (here, Apple’s FileMerge, i.e., opendiff)

• Non-conflicting julia> hg merge merging pizza.txt portions merged 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) automatically • Manually resolve conflicting portions • Choose left, right, both, or neither • See & edit final text in bottom pane • Save file & quit

34 Incoming Your code code

Merged code

35 Incoming Your code code

Merged code

36 • Save file & quit Merge with conflict: verify & commit!

julia> hg heads julia> hg diff -r 9 changeset: 9:f41d23390194 1/2 cup bell peppers, thinly sliced summary: peppers -1/3 cup mushrooms ! +1/3 cup mushrooms, sliced changeset: 8:791c8abf0a1d +1/4 cup onions, diced summary: onions 1/2 cup Italian sausage, cooked ! ! julia> hg diff -r 8 Preheat oven to 450 °F. 3 1/2 cups bread flour -Divide dough in half; roll out to 10–12 inches diameter. -2 Tbsp olive oil +Divide dough in half; spin in air to 10–12 inches diameter. -2 tsp salt Spread with tomato sauce & sprinkle with toppings. +2 Tbsp extra virgin olive oil ! +2 tsp sea salt julia> hg commit -m ‘merge’ 1 tsp sugar ! 2/3 cup mozzarella cheese, grated -1/4 cup mushrooms, sliced +1/2 cup bell peppers, thinly sliced +1/3 cup mushrooms, sliced 1/4 cup onions, diced

37 Merge with conflict: manual • hg resolve [-l, -m, -u] [files] pizza.txt Dough • -l list resolved status 1 1/2 cups warm water (105 °F–115 °F) 1 package active dry yeast • -m mark as resolved 3 1/2 cups bread flour 2 Tbsp extra virgin olive oil • -u mark as unresolved 2 tsp sea salt 1 tsp sugar julia> hg merge --tool internal:merge ! merging pizza.txt Toppings warning: conflicts while merging pizza.txt! (edit, then use 'hg resolve --mark') 2/3 cup tomato sauce 0 files updated, 0 files merged, 0 files removed, 1 files unresolved 2/3 cup mozzarella cheese, grated use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon <<<<<<< local ! 1/4 cup mushrooms, sliced julia> hg commit -m 'merge' 1/4 cup onions, diced abort: unresolved merge conflicts (see "hg help resolve") ======! 1/2 cup bell peppers, thinly sliced julia> hg resolve -l # list resolved status 1/3 cup mushrooms U pizza.txt # U = unresolved >>>>>>> other ! 1/2 cup Italian sausage, cooked julia> jedit pizza.txt ! julia> hg resolve -m pizza.txt # mark as resolved Mix dough ingredients; knead for 10 minutes. (no more unresolved files) ! julia> hg resolve -l R pizza.txt # R = resolved ! julia> hg commit -m ‘merge’

38 History • hg log -G # graph branches • hg glog # alias in ~/.hgrc

chris> hg log -G | @ changeset: 10:10ae7218a2bd o changeset: 6:800444945b16 |\ tag: tip |\ parent: 5:b1473e48944e | | parent: 9:791c8abf0a1d | | parent: 4:962db491f9ca | | parent: 8:f41d23390194 | | summary: merge | | summary: merge | | | | | o changeset: 5:b1473e48944e | o changeset: 9:791c8abf0a1d | | parent: 3:0f66f034fa18 | | parent: 7:1b946d5db238 | | summary: ham | | summary: onions | | | | o | changeset: 4:962db491f9ca o | changeset: 8:f41d23390194 |/ summary: veggies |/ summary: peppers | | o changeset: 3:0f66f034fa18 o changeset: 7:1b946d5db238 | summary: preheat | summary: basic | | o changeset: 2:7d60311ab431 . | summary: meat . | . o changeset: 1:92dafa80df69 ! | summary: feta | o changeset: 0:9ab04aa4c434 summary: start pizza

39 Solving merge problems

40 Fixing bad merge (option 1) • hg update --clean • Reverts all files to state before “hg merge” command

! julia> hg merge merging pizza.txt ! 2016-11-04 01:24:24.700 FileMerge[21657:d07] Invalid color System, labelColor (warning given only once) 0 files updated, 1 files merged, 0 files removed, 0 files unresolved ! (branch merge, don't forget to commit) ! ! # utter confusion entails! julia> hg up ! abort: outstanding uncommitted merge ! ! julia> hg st M pizza.txt ! ! julia> hg update --clean ! 1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1 other heads for branch “default" ! ! julia> hg st julia> • Can then do “hg merge” again

41 Fixing bad merge (option 2) • Alternatively, redo merge of specific files • hg resolve -u files # mark files as unresolved • hg resolve files # re-merge files julia> hg merge merging pizza.txt 2016-11-04 01:26:51.567 FileMerge[21675:d07] Invalid color System, labelColor (warning given only once) 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) ! julia> hg resolve -l R pizza.txt # R = resolved julia> hg resolve -u pizza.txt julia> hg resolve -l U pizza.txt # U = unresolved ! julia> hg resolve pizza.txt merging pizza.txt 2016-11-04 01:28:11.805 FileMerge[21690:d07] Invalid color System, labelColor (warning given only once) (no more unresolved files) julia> hg st M pizza.txt julia> hg commit -m 'merge'

42 Merge with uncommitted changes

recipes> hg st • hg won’t merge if there M pizza.txt ! are uncommitted changes recipes> hg merge abort: uncommitted changes (use 'hg status' to list changes) • Either commit them, ! recipes> hg shelve -n peppers shelved as peppers or shelve them temporarily 1 files updated, 0 files merged, 0 files removed, 0 files unresolved ! • hg shelve [-n name] [-l] recipes> hg st recipes> hg shelve -l peppers (4s ago) changes to: meat • hg unshelve [name] ! recipes> hg merge merging pizza.txt • Extension in ~/.hgrc 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) ! recipes> hg commit -m 'merge' ! recipes> hg unshelve [peppers] ! unshelving change 'peppers' rebasing shelved changes rebasing 4:8be446f41b74 "changes to: meat" (tip) merging pizza.txt • (Similar to git stash) recipes> hg st M pizza.txt

43 Bookmarks

44 Branching with Bookmarks main • Bookmark is label that 15: merge main sauce tracks head of a branch 13: spin 14: chop main sauce • Add, delete, and rename 12: ham 11: merge at any time sauce main 10: peel 8: parm. sauce • Typically for short-lived main 9: onion feature or bug-fix branches 7: merge main sauce • Essentially same as git’s 5: preheat 6: sauté sauce branches 3: brand main sauce 4: meat 2: sauce sauce main 1: feta

0: pizza

45 Branching with Bookmarks • hg bookmark[s] # lists bookmarks • hg bookmark name # creates bookmark • hg update name # updates working copy to bookmark

recipes> jedit pizza.txt recipes> hg add pizza.txt recipes> hg commit -m 'pizza' ! recipes> jedit pizza.txt recipes> hg commit -m 'feta' ! recipes> hg bookmark main recipes> hg bookmark sauce recipes> hg bookmarks main 1:a1f2a82ea6e0 * sauce 1:a1f2a82ea6e0 sauce main 1: feta

0: pizza

46 Branching with Bookmarks recipes> jedit sauce.txt recipes> hg add sauce.txt recipes> hg commit -m 'sauce' ! recipes> jedit sauce.txt recipes> hg commit -m 'brand' recipes> ls pizza.txt sauce.txt ! recipes> hg slog -G @ @3 brand default [*sauce] (tip) | o 2 sauce default | o 1 feta default [main] | o 0 pizza default sauce 3: brand sauce 2: sauce sauce main 1: feta

0: pizza

47 Branching with Bookmarks recipes> hg up main 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (activating bookmark main) recipes> ls pizza.txt ! recipes> jedit pizza.txt recipes> hg commit -m 'meat' created new head ! recipes> hg commit -m 'preheat' recipes> hg slog -G @ @5 preheat default [*main] (tip) | o 4 meat default main | 5: preheat | o 3 brand default [sauce] | | sauce | o 2 sauce default 3: brand |/ o 1 feta default main | 4: meat 2: sauce o 0 pizza default main 1: feta

0: pizza

48 Branching with Bookmarks recipes> hg up sauce 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (activating bookmark sauce) recipes> hg slog -G o 5 preheat default [main] | o 4 meat default | | @ @3 brand default [*sauce] | | | o 2 sauce default |/ o 1 feta default | o 0 pizza default ! main sauce recipes> jedit sauce.txt 5: preheat 6: sauté recipes> hg commit -m 'saute' recipes> hg slog -G sauce @ @6 saute default [*sauce] 3: brand | | o 5 preheat default [main] | | 4: meat 2: sauce | o 4 meat default | | o | 3 brand default 1: feta | | o | 2 sauce default 0: pizza |/ o 1 feta default | o 0 pizza default 49 Branching with Bookmarks recipes> hg up main 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (activating bookmark main) recipes> hg slog -G o 6 saute default [sauce] | | @ @5 preheat default [*main] | | ! recipes> hg merge sauce 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) main recipes> st 7: merge M sauce.txt recipes> hg commit -m 'merge sauce' main sauce recipes> hg slog -G 5: preheat 6: sauté @ @7 merge sauce default 5,6 [*main] |\ | o 6 saute default [sauce] 3: brand | | o | 5 preheat default | | 4: meat 2: sauce o | 4 meat default | | | o 3 brand default 1: feta | | | o 2 sauce default |/ 0: pizza o 1 feta default | o 0 pizza default 50 Branching with Bookmarks recipes> hg bookmark * main 7:92bf22ea6bd9 sauce 6:058a19c7aec7 recipes> jedit pizza.txt recipes> hg commit -m 'parmesan' ! recipes> hg up sauce 1 files updated, 0 files merged, 0 files removed, 0 files unresolved sauce (activating bookmark sauce) 10: peel recipes> jedit sauce.txt main 8: parm. recipes> hg commit -m 'onion' sauce created new head 9: onion ! main 7: merge recipes> hg commit -m 'peeled' recipes> hg slog -G sauce @ @10 peeled default [*sauce] 5: preheat 6: sauté | o 9 onion default | 3: brand | o 8 parmesan default [main] | | | o 7 merge sauce default 5,6 4: meat 2: sauce |/| o | 6 saute default | | 1: feta | o 5 preheat default | | | o 4 meat default 0: pizza | |

51 Branching with Bookmarks recipes> hg merge main 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) recipes> hg st M pizza.txt sauce recipes> hg commit -m 'merge main' 11: merge recipes> hg slog -G @ @11 merge main default 10,8 [*sauce] sauce |\ 10: peel | o 10 peeled default main | | 8: parm. | o 9 onion default 9: onion | | o | 8 parmesan default [main] 7: merge | | o | 7 merge sauce default 5,6 |\| 5: preheat 6: sauté | o 6 saute default | | o | 5 preheat default 3: brand | | o | 4 meat default | | 4: meat 2: sauce | o 3 brand default | | | o 2 sauce default 1: feta |/ o 1 feta default | 0: pizza o 0 pizza default

52 Branching with Bookmarks recipes> hg up main main 1 files updated, 0 files merged, 15: merge 0 files removed, 0 files unresolved (activating bookmark main) main sauce ! 13: spin 14: chop recipes> jedit pizza.txt main sauce recipes> hg commit -m 'ham' 12: ham 11: merge created new head ! recipes> jedit pizza.txt 10: peel recipes> hg commit -m 'spin' main ! 8: parm. recipes> hg up sauce 9: onion 2 files updated, 0 files merged, 7: merge 0 files removed, 0 files unresolved (activating bookmark sauce) recipes> jedit sauce.txt 5: preheat 6: sauté recipes> hg commit -m 'chop' ! recipes> hg up main 3: brand 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (activating bookmark main) 4: meat 2: sauce ! recipes> hg merge sauce 1 files updated, 0 files merged, 1: feta 0 files removed, 0 files unresolved (branch merge, don't forget to commit) recipes> hg commit -m 'merge sauce' 0: pizza

53 Branching with Bookmarks recipes> hg bookmark --delete sauce main 15: merge recipes> hg slog -G @ @15 merge sauce default 13,14 [*main] sauce |\ 13: spin 14: chop | o 14 chop default | | o | 13 spin default 12: ham 11: merge | | o | 12 ham default | | 10: peel | o 11 merge main default 10,8 |/| 8: parm. | o 10 peeled default 9: onion | | | o 9 onion default 7: merge | | o | 8 parmesan default | | 5: preheat 6: sauté o | 7 merge sauce default 5,6 |\| | o 6 saute default 3: brand | | o | 5 preheat default | | 4: meat 2: sauce o | 4 meat default | | | o 3 brand default 1: feta | | | o 2 sauce default |/ 0: pizza o 1 feta default | o 0 pizza default 54 Pushing bookmarks • hg doesn’t push new bookmarks by default • hg push {--bookmark|-B} bookmark

recipes> hg push pushing to server searching for changes abort: push creates new remote head 42ca2b91c349 with bookmark 'sauce'! (merge or see "hg help push" for details about pushing new heads) ! recipes> hg push --bookmark main # or -B pushing to ../c2 searching for changes adding changesets adding manifests adding file changes added 2 changesets with 2 changes to 1 files exporting bookmark main ! recipes> hg push --bookmark sauce # or -B pushing to ../c2 searching for changes adding changesets adding manifests adding file changes added 2 changesets with 2 changes to 1 files (+1 heads) exporting bookmark sauce

55 Merging divergent bookmarks • Chris & Julia both make changes in sauce branch, Julia pulls in new head as sauce@default

julia> hg pull -u julia> hg merge pulling from server abort: no matching bookmark to merge - please searching for changes merge with an explicit rev or bookmark adding changesets (run 'hg heads' to see all heads) adding manifests ! adding file changes julia> hg up sauce added 1 changesets with 1 changes to 1 files (+1 heads) 2 files updated, 0 files merged, 0 files divergent bookmark sauce stored as sauce@default removed, 0 files unresolved 0 files updated, 0 files merged, (activating bookmark sauce) 0 files removed, 0 files unresolved ! 1 other divergent bookmarks for "sauce" julia> hg bookmarks ! main 4:8f439fe17062 julia> hg heads * sauce 12:4d0841e8279d changeset: 10:207f29b01f7b sauce@default 13:bd2c99f8da7f bookmark: sauce@default ! parent: 8:b6b112e27e33 julia> hg merge summary: finely merging sauce.txt ! 0 files updated, 1 files merged, 0 files changeset: 9:566cd34821bc removed, 0 files unresolved bookmark: sauce (branch merge, don't forget to commit) summary: vidalia ! ! julia> hg commit -m 'merge' changeset: 2:8f439fe17062 bookmark: main summary: pepperoni

56 Named Branches

57 Branching with Named Branches default • Branch is permanent name 15: merge default sauce attached to each commit 13: spin 14: chop default sauce • “default” branch 12: ham 11: merge sauce • Typically for long-lived default 10: peel 8: parm. sauce branches like “stable” and default 9: onion “devel” 7: merge default sauce • Operate similarly to 5: preheat 6: sauté sauce bookmarks 3: brand default sauce 4: meat 2: sauce default 1: feta default 0: pizza

58 Branching with Named Branches • hg branches # lists branches • hg branch name # creates branch • hg update name # updates working copy to branch • hg commit --close-branch [-m “message”]

recipes> jedit pizza.txt recipes> hg add pizza.txt recipes> hg commit -m pizza ! recipes> jedit pizza.txt recipes> hg commit -m feta ! recipes> hg branch sauce marked working directory as branch sauce (branches are permanent and global, did you want a bookmark?) default ! 1: feta recipes> hg branches # new branch not yet visible default 1:98b3df1d5afe default 0: pizza

59 Branching with Bookmarks recipes> jedit sauce.txt recipes> hg add sauce.txt recipes> hg commit -m start sauce recipes> hg branches # new branch visible sauce 2:2a5c5e403030 default 1:98b3df1d5afe (inactive) ! recipes> jedit sauce.txt recipes> hg commit -m 'brand' recipes> ls pizza.txt sauce.txt ! recipes> hg slog -G @ @3 brand sauce | o 2 start sauce | o 1 feta default | sauce o 0 pizza default 3: brand sauce 2: sauce default 1: feta default 0: pizza

60 Branching with Named Branches recipes> hg up default 0 files updated, 0 files merged, 1 files removed, 0 files unresolved ! recipes> ls pizza.txt ! recipes> jedit pizza.txt recipes> hg commit -m 'meat' ! recipes> hg commit -m 'preheat' recipes> hg slog -G @ @5 preheat default | o 4 meat default | default | o 3 brand sauce 5: preheat | | | o 2 start sauce sauce |/ 3: brand o 1 feta default | default sauce o 0 pizza default 4: meat 2: sauce default 1: feta default 0: pizza

61 Branching with Named Branches recipes> hg up sauce 2 files updated, 0 files merged, 0 files removed, 0 files unresolved ! recipes> hg slog -G o 5 preheat default | o 4 meat default | | @ @3 brand sauce | | | o 2 start sauce |/ o 1 feta default | o 0 pizza default ! default sauce recipes> jedit sauce.txt 5: preheat 6: sauté recipes> hg commit -m 'saute' recipes> hg slog -G sauce @ @6 saute sauce 3: brand | | o 5 preheat default default sauce | | 4: meat 2: sauce | o 4 meat default | | default o | 3 brand sauce 1: feta | | o | 2 start sauce default 0: pizza |/ o 1 feta default | o 0 pizza default 62 Branching with Named Branches recipes> hg up default 1 files updated, 0 files merged, 1 files removed, 0 files unresolved ! recipes> hg slog -G o 6 saute sauce | | @ @5 preheat default | | ! recipes> hg merge sauce 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) default recipes> hg st 7: merge M sauce.txt default sauce recipes> hg commit -m 'merge sauce' 5: preheat 6: sauté recipes> hg slog -G @ @7 merge sauce default 5,6 sauce |\ 3: brand | o 6 saute sauce | | default sauce o | 5 preheat default 4: meat 2: sauce | | o | 4 meat default default | | 1: feta | o 3 brand sauce | | default | o 2 start sauce 0: pizza |/ o 1 feta default | 63 o 0 pizza default Branching with Named Branches recipes> hg branches sauce 2:2a5c5e403030 (inactive) default 1:98b3df1d5afe recipes> jedit pizza.txt recipes> hg commit -m 'parmesan' ! recipes> hg up sauce 1 files updated, 0 files merged, 0 files removed, 0 files unresolved sauce ! 10: peel recipes> jedit sauce.txt default 8: parm. recipes> hg commit -m 'onion' sauce ! default 9: onion recipes> hg commit -m 'peeled' 7: merge recipes> hg slog -G @ @10 peeled sauce default sauce | 5: preheat 6: sauté o 9 onion sauce | sauce | o 8 parmesan default 3: brand | | | o 7 merge default 5,6 default sauce |/| 4: meat 2: sauce o | 6 saute sauce | | default | o 5 preheat default 1: feta | | | o 4 meat default default | | 0: pizza

64 Branching with Named Branches recipes> hg merge default 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) recipes> hg st M pizza.txt sauce recipes> hg commit -m 'merge default' 11: merge recipes> hg slog -G @ @11 merge sauce 10,8 sauce |\ 10: peel | o 10 peeled sauce default | | 8: parm. sauce | o 9 onion sauce 9: onion | | default o | 8 parmesan default 7: merge | | o | 7 merge default 5,6 default sauce |\| 5: preheat 6: sauté | o 6 saute sauce | | sauce o | 5 preheat default 3: brand | | o | 4 meat default default sauce | | 4: meat 2: sauce | o 3 brand sauce | | default | o 2 start sauce 1: feta |/ o 1 feta default default | 0: pizza o 0 pizza default

65 Branching with Named Branches recipes> hg up default default 1 files updated, 0 files merged, 15: merge 0 files removed, 0 files unresolved ! default sauce 13: spin 14: chop recipes> jedit pizza.txt recipes> hg commit -m 'ham' default sauce ! 12: ham 11: merge recipes> jedit pizza.txt recipes> hg commit -m 'spin' sauce ! 10: peel recipes> hg up sauce default 8: parm. 2 files updated, 0 files merged, sauce 0 files removed, 0 files unresolved default 9: onion recipes> jedit sauce.txt 7: merge recipes> hg commit -m ‘chop' --close-branch ! default sauce recipes> hg branches 5: preheat 6: sauté default 15:dd9a3e61378b ! sauce recipes> hg branches --closed # or -c 3: brand default 15:dd9a3e61378b sauce 14:c6e4f6cf0870 (closed) default sauce ! 4: meat 2: sauce recipes> hg up default 2 files updated, 0 files merged, default 0 files removed, 0 files unresolved 1: feta ! recipes> hg merge sauce default 0: pizza 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) 66 recipes> hg commit -m 'merge sauce' Branching with Named Branches recipes> hg slog -G default @ @15 merge default 13,14 15: merge |\ | _ 14 chop sauce default sauce | | closed 13: spin 14: chop o | 13 spin default branch | | default sauce 11: merge o | 12 ham default 12: ham | | sauce | o 11 merge sauce 10,8 |/| default 10: peel | o 10 peeled sauce 8: parm. | | sauce | o 9 onion sauce default 9: onion | | 7: merge o | 8 parmesan default | | default sauce o | 7 merge default 5,6 5: preheat 6: sauté |\| | o 6 saute sauce sauce | | 3: brand o | 5 preheat default | | default sauce o | 4 meat default 4: meat 2: sauce | | | o 3 brand sauce default | | 1: feta | o 2 start sauce |/ default o 1 feta default 0: pizza | o 0 pizza default

67 Pushing branches • hg doesn’t push new branches by default • hg pushes all branches by default • (git pushes only the current branch, which makes more sense to me) • hg push [-b branch] [--new-branch]

recipes> hg push pushing to server searching for changes abort: push creates new remote branches: sauce! (use 'hg push --new-branch' to create new remote branches) ! recipes> hg push -b default pushing to server searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files ! recipes> hg push -b sauce --new-branch pushing to server searching for changes adding changesets adding manifests adding file changes 68 added 2 changesets with 2 changes to 1 files (+1 heads) Merging branch heads

julia> hg up default 1 files updated, 0 files merged, 1 files removed, julia> hg pull 0 files unresolved pulling from server julia> hg merge searching for changes abort: branch 'default' has one head - please adding changesets merge with an explicit rev adding manifests (run 'hg heads' to see all heads) adding file changes ! added 1 changesets with 1 changes to 1 files julia> hg up sauce (+1 heads) 2 files updated, 0 files merged, 0 files removed, (run 'hg heads' to see heads, 'hg merge' to merge) 0 files unresolved ! julia> hg merge julia> hg branches merging sauce.txt sauce 4:75a9cc02c946 0 files updated, 1 files merged, 0 files removed, default 1:df75056e704f 0 files unresolved julia> hg heads (branch merge, don't forget to commit) changeset: 5:0cc37f014583 julia> hg commit -m 'merge' branch: sauce ! parent: 3:23cdd918e993 julia> hg slog -G summary: finely diced @ | @6 merge sauce 5,4 ! |\ \ changeset: 4:75a9cc02c946 | o | 5 fine diced sauce branch: sauce | | | parent: 3:23cdd918e993 o | | 4 diced sauce summary: diced |/ / ! o | 3 onion sauce changeset: 1:df75056e704f | | summary: meat o | 2 start sauce | | | o 1 meat default |/ 69 o 0 pizza default Outline • Basic commands in single repository • Creating repo • Add & edit files • Viewing history • Fixing last commit • Multiple users / branches • Simple case • Merge without conflicts • Merge with conflicts • Bookmarks • Branches • BitBucket • Fork • Pull requests • Final thoughts

70 BitBucket • SSH key setup • View profile > BitBucket settings > SSH keys > Add key • Creating repository • Repositories > Create Repository • Fork • In main repo: “...” > Fork > Fork Repository • Pull request • In forked repo: Pull requests > Create a pull request > Create • Approving pull request • In main repo: Pull requests > select pull request > Merge

71 Outline • Basic commands in single repository • Creating repo • Add & edit files • Viewing history • Fixing last commit • Multiple users / branches • Simple case • Merge without conflicts • Merge with conflicts • Bookmarks • Branches • BitBucket • Fork • Pull requests • Final thoughts

72 Hooks • Run on actions (commit, push, pull, ...) • Run on client (under user’s control) or on server • Can verify that action is allowed

! .hg/hgrc [hooks] ! # disallow tab anywhere or trailing whitespace # run before commit transaction finishes ! # see http://hgbook.red-bean.com/read/handling-repository-events-with-hooks.html # (here matching \t fixed using GNU’s --perl-regexp option) ! pretxncommit = hg export tip | (! grep --perl-regexp '^\+.*(\t| $)') ! • Can run scripts, such as emailing notifications, posting to bugzilla, testing compilation, etc. • BitBucket handles many of these features for us

73 Other useful commands • hg outgoing # hg out • hg incoming # hg in • Tells what commits would be pushed or pulled, respectively • hg update --rebase • Rewrite history to avoid merge • hg commit --interactive # or -i • Allows committing some portion of changes

74 Further resources • Mercurial website • https://www.mercurial-scm.org/guide • https://www.mercurial-scm.org/wiki/BeginnersGuides • Mercurial: The Definitive Guide (2009) • Online book • http://hgbook.red-bean.com/ • hginit tutorial • http://hginit.com/ • A Guide to Branching in Mercurial (2009) • http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/

75 Mercurial Quick Reference • Create • Branching & merging hg init [dir] hg merge [rev | branch | bookmark] hg clone url [dir] hg update [rev | branch | bookmark | tag] # hg up (alias hg checkout) • Files hg update --clean . # cancel uncommitted merge hg add files hg resolve [-l | -m files] hg mv [-A] source dest hg bookmark [--delete] [name] hg cp [-A] source dest hg branch [name] hg rm [-A] files hg branches hg revert files hg tag [-r rev] [--local] name

• Commits • Viewing changes & history hg commit [-m “message”] [--amend] [files] hg diff [-c rev] [-r rev] [-w -b -B] [files] [--close-branch] hg log [-l num] [-G] [--stat] [files] hg pull [url] [-u] hg status [-acmq] [files] # hg st hg push [url] [-b branch | -B bookmark | -r rev] hg blame [-un] [files] hg rollback hg heads hg outgoing [url] hg incoming [url] • Configuration files ~/.hgrc # user ~/.hgignore # user, set in ~/.hgrc .hg/hgrc # repo .hgignore # repo

76