22
What every programmer should know about merging branches in Mercurial Sergey Kishchenko Quickoffice October 11, 2012 Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in Mercurial October 11, 2012 1 / 22

What every programmer should know about merging branches in Mercurial

Embed Size (px)

DESCRIPTION

Slides for a talk on merging branches in Mercurial that I did on Oct 11, 2012 at Quickoffice

Citation preview

Page 1: What every programmer should know about merging branches in Mercurial

What every programmer should know about mergingbranches in Mercurial

Sergey Kishchenko

Quickoffice

October 11, 2012

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 1 / 22

Page 2: What every programmer should know about merging branches in Mercurial

Branches

Two different branches Two different defaults

NOTE: Different repos cloned from one source are not actuallydifferent, they are essentially same repo. You can transfer changesetsbetween them with push and pull

IMPORTANT: Named branches in Mercurial are permanent!

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 2 / 22

Page 3: What every programmer should know about merging branches in Mercurial

Pull

First step in merge process: pulling remote changes

> hg pull -b REMOTE_BRANCH REMOTE_REPO

Pulling change pulls also all its ancestors → unneeded changesPulling changes may result in creating new heads → merge is neededPulling branch pulls also all branches it’s based on → merge is needed

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 3 / 22

Page 4: What every programmer should know about merging branches in Mercurial

Solution attempt: ”early-fix” branch

Bad idea Good idea

Having a specific fix branch allows pulling this branch without pullingother changes (Feature A)

You should think about it in advance and you’re not a psychic

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 4 / 22

Page 5: What every programmer should know about merging branches in Mercurial

Solution attempt: Patch

IDEA: Why do we even need to use pull?

Fix A can be based on Feature A so patch will not apply smoothly

SCM can’t guess that Fix A and Fix B are actually the same and should beused as base when merging Fix C

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 5 / 22

Page 6: What every programmer should know about merging branches in Mercurial

Solution attempt: graft

Using graft

> hg graft --log GRAFT_REVISION

graft uses 3-way merge and deals fine with Fix A being based on Feature A

SCM still can’t guess that Fix A and Fix A’ are actually the same andshould be used as base when merging Fix C

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 6 / 22

Page 7: What every programmer should know about merging branches in Mercurial

Solution attempt: grafting from remote repo

graft doesn’t deal with changesets from the remote repo at the momentbecause it needs all of the changes to do 3-way merge. But it’s possible tostrip changes when they are not needed anymore

grafting from remote repository

> hg incoming --template="{node} " REMOTE_REPO -q \

-r GRAFT_REVISION > TEMP_FILE

> hg pull -r GRAFT_REVISION REMOTE_REPO

> hg graft --log GRAFT_REVISION

> hg strip ‘cat TEMP_FILE‘

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 7 / 22

Page 8: What every programmer should know about merging branches in Mercurial

Solution attempt: dealing with base issues with graft

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 8 / 22

Page 9: What every programmer should know about merging branches in Mercurial

Solution attempt: dealing with base issues with graft

Searching for grafted revisions

> hg log -r "ancestor(LOCAL_HEAD,OTHER_HEAD)::LOCAL_HEAD" \

-k "grafted" -v

e.g.

> hg log -r "ancestor(d5c1ff557965,927d19ecf38e)::d5c1ff557965" \

-k "grafted" -v

graft-aware merging

> hg merge -R GRAFT_REVISION

> hg merge

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 9 / 22

Page 10: What every programmer should know about merging branches in Mercurial

Solution attempt: Branches alternatives

Bookmarks: http://mercurial.selenic.com/wiki/Bookmarks

Lightweight git-like branches, good for local hacking, distributedalong with Mercurial.

Several heads on default branch, no trail in history

Local branches, lbranches:http://mercurial.selenic.com/wiki/LocalbranchExtension.

Lightweight repo clones, good for local hacking

Just a local feature

Patch queues, mq:http://mercurial.selenic.com/wiki/MqExtension

Patch series, editable history, distributed along with Mercurial

Just a local feature

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 10 / 22

Page 11: What every programmer should know about merging branches in Mercurial

Merge

Merging different branches

> hg co local_branch

> hg merge remote_branch

> hg ci -m merge

Merging heads in default branch

> hg merge

(while in default branch)

> hg ci -m merge

Looks easy, huh? But it is not easy at all because of possible conflicts

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 11 / 22

Page 12: What every programmer should know about merging branches in Mercurial

Merge problem: too many conflicts

Why occurs?Synchronizing rarelyTight coupling of the componentsToo many developers for one componentStoring autogenerated code in the tree

How to prevent?Synchronize oftenSimplify connections between componentsDesign clear and minimalistic APINotify other developers of the component when doing changesDon’t exceed the reasonable amount of developers for one componentDo not store autogenerated code in the tree

How to deal with?Use a good graphical merge tool that allows 3-way mergingLearn how to use the resolve command

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 12 / 22

Page 13: What every programmer should know about merging branches in Mercurial

3-way merge

Merged (M)

line1 modified

line2

Base (B)

line1

Local (L)

line1

line2

Remote (R)

line1 modified

Without base it’s hard to merge Local and Remote files: it’s hard tounderstand was it a removal of ”line2” and addition of ” modified” orremoval of ” modified” and addition of ”line2” → use a 3-way graphicalmerge toolSubjective choice: http://mercurial.selenic.com/wiki/KDiff3

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 13 / 22

Page 14: What every programmer should know about merging branches in Mercurial

resolve command

Imagine you need to merge a lot of changes

Bad idea

> hg merge # non-stop merging, here I come!

Good idea> hg merge -t "internal:merge" # does the best it can automatically

> hg resolve -l # shows merge state

> hg resolve FILE # runs conflict resolving for specific file

> hg resolve -a # runs conflict resolving for all unresolved files

IMPORTANT: Unfortunately, resolve command doesn’t save progresswhen interrupted. There is an issue for that:http://bz.selenic.com/show_bug.cgi?id=3638.Possible workaround: iterate through conflicts and call resolve for each file

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 14 / 22

Page 15: What every programmer should know about merging branches in Mercurial

Merge problem: hard to understand the conflict

Also known as ”I don’t know which change is correct”

Why occurs?Synchronizing rarely → forgetting what was going onMerging components without component knowledge

How to prevent?Synchronize oftenSpread the components knowledge among developers → codecross-review

How to deal with?Use help from those who have good component knowledgeLearn how to use log (shows the history) and blame (shows who is theauthor of the changes) command

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 15 / 22

Page 16: What every programmer should know about merging branches in Mercurial

Merge problem: code was refactored

Also known as ”It seems the code was removed remotely so I can drop thelocal change” (immediately eaten by velociraptor)

Why occurs?Doing the refactoring and not merging it into all branches immediatelyMerging refactored components without component knowledge

How to prevent?Spread the ongoing refactoring knowledge among developers → codecross-reviewUse ”early-fix” branch for refactoring and merge it immediately ornotify everyone about it

How to deal with?Use help from those who have good knowledge about the refactoringUse 3-way merge (check next slide)In case different refactoring was done in both local and remoteversions, you’re DOOMed :(

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 16 / 22

Page 17: What every programmer should know about merging branches in Mercurial

Using 3-way merge for merging refactored code

1 Use 3-way merge graphical tool to see base(B), local(L) andremote(R) version of a file

2 Let’s assume refactoring was done only in remote. It means thatbase-local difference is not large, it’s all about modifying names,adding params, issues fix, etc. Base and remote differ a lot, often theremote version is completely missing, i.e., was moved to different file.

3 Use log to identify what was refactoring about. E.g., you can find thefile that is a new home for the code that is missing from the R

Use log to find refactoring changesets

> hg log --follow R

4 Iterate through base-local differences change by change and applythem to the code in a correct place

5 In any case consider contacting those who did the refactoring for helpand/or code review

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 17 / 22

Page 18: What every programmer should know about merging branches in Mercurial

Merge problem: non-source files conflicts

Why occurs?Modifying the resource/project file and not merging it into all branchesimmediatelyStoring user settings in the treeSynchronizing rarelyPointless modification of project files/resources

How to prevent?Avoid pointless modification of non-source filesConsider using an ”early-fix” branch for non-source file modificationand merge it into all branches immediatelyDo not store user settings in the treeConsider storing mergeable sources instead of the non-source products

How to deal with?Consider using a specialized tools to merge specific filesIn case files are not mergeable choose either local or remote versionand try to reproduce all of the changes from the other version

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 18 / 22

Page 19: What every programmer should know about merging branches in Mercurial

One more time: good things

Using branches wisely

Specifying branch for pulling and pushing

Using graft

Using good graphical tool for merging

Using 3-way merge

Using ”early-fix” branches

Getting knowledge from others when merging theirs code

Providing help to those who merge your code

Providing a good description for the changes

Using hg cp and hg mv commands to copy and rename/move files

Cross-code reviews

Small self-contained changesets

Writing easy understandable code!

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 19 / 22

Page 20: What every programmer should know about merging branches in Mercurial

One more time: bad things

Manual merges

Applying patches manually

Being a coward and selecting either local or remote version withoutchecking it

Trusting automatic merge tools completely

Using bad names for branches

Using --force flag

Copying and moving files without using hg cp/hg mv

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 20 / 22

Page 21: What every programmer should know about merging branches in Mercurial

One more time: things to avoid

Doing a refactoring that can’t be merged into all branchesimmediately

Modifying non-source file without merging it into all branchesimmediately

Modifying a component that somebody is working on withoutnotifying this person

Storing autogenerated code and user settings in the code tree

Using branches without bookmarking or naming them

Committing all of the changes in one changeset

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 21 / 22

Page 22: What every programmer should know about merging branches in Mercurial

Thank you! Questions?

Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 22 / 22