Anda di halaman 1dari 22

What every programmer should know about merging branches in Mercurial

Sergey Kishchenko
Quickoce

October 11, 2012

Sergey Kishchenko (Quickoce)

What every programmer should know about merging branches in Mercurial October 11, 2012

1 / 22

Branches
Two dierent branches Two dierent defaults

NOTE: Dierent repos cloned from one source are not actually dierent, they are essentially same repo. You can transfer changesets between them with push and pull IMPORTANT: Named branches in Mercurial are permanent!
Sergey Kishchenko (Quickoce) What every programmer should know about merging branches in Mercurial October 11, 2012 2 / 22

Pull
First step in merge process: pulling remote changes > hg pull -b REMOTE_BRANCH REMOTE_REPO

Pulling change pulls also all its ancestors unneeded changes Pulling changes may result in creating new heads merge is needed Pulling branch pulls also all branches its based on merge is needed
Sergey Kishchenko (Quickoce) What every programmer should know about merging branches in Mercurial October 11, 2012 3 / 22

Solution attempt: early-x branch

Bad idea

Good idea

Having a specic x branch allows pulling this branch without pulling other changes (Feature A) You should think about it in advance and youre not a psychic

Sergey Kishchenko (Quickoce)

What every programmer should know about merging branches in Mercurial October 11, 2012

4 / 22

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 cant guess that Fix A and Fix B are actually the same and should be used as base when merging Fix C
Sergey Kishchenko (Quickoce) What every programmer should know about merging branches in Mercurial October 11, 2012 5 / 22

Solution attempt: graft


Using graft > hg graft --log GRAFT_REVISION

graft uses 3-way merge and deals ne with Fix A being based on Feature A SCM still cant guess that Fix A and Fix A are actually the same and should be used as base when merging Fix C
Sergey Kishchenko (Quickoce) What every programmer should know about merging branches in Mercurial October 11, 2012 6 / 22

Solution attempt: grafting from remote repo

graft doesnt deal with changesets from the remote repo at the moment because it needs all of the changes to do 3-way merge. But its possible to strip 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 (Quickoce)

What every programmer should know about merging branches in Mercurial October 11, 2012

7 / 22

Solution attempt: dealing with base issues with graft

Sergey Kishchenko (Quickoce)

What every programmer should know about merging branches in Mercurial October 11, 2012

8 / 22

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 (Quickoce)

What every programmer should know about merging branches in Mercurial October 11, 2012

9 / 22

Solution attempt: Branches alternatives


Bookmarks: http://mercurial.selenic.com/wiki/Bookmarks Lightweight git-like branches, good for local hacking, distributed along 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 (Quickoce) What every programmer should know about merging branches in Mercurial October 11, 2012 10 / 22

Merge
Merging dierent 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 conicts
Sergey Kishchenko (Quickoce) What every programmer should know about merging branches in Mercurial October 11, 2012 11 / 22

Merge problem: too many conicts


Why occurs?
Synchronizing rarely Tight coupling of the components Too many developers for one component Storing autogenerated code in the tree

How to prevent?
Synchronize often Simplify connections between components Design clear and minimalistic API Notify other developers of the component when doing changes Dont exceed the reasonable amount of developers for one component Do not store autogenerated code in the tree

How to deal with?


Use a good graphical merge tool that allows 3-way merging Learn how to use the resolve command
Sergey Kishchenko (Quickoce) What every programmer should know about merging branches in Mercurial October 11, 2012 12 / 22

3-way merge
Base (B) line1 Local (L) line1 line2 Merged (M) line1 modified line2 Remote (R) line1 modified

Without base its hard to merge Local and Remote les: its hard to understand was it a removal of line2 and addition of modied or removal of modied and addition of line2 use a 3-way graphical merge tool Subjective choice: http://mercurial.selenic.com/wiki/KDiff3
Sergey Kishchenko (Quickoce) What every programmer should know about merging branches in Mercurial October 11, 2012 13 / 22

resolve command
Imagine you need to merge a lot of changes Bad idea > hg merge # non-stop merging, here I come! Good idea
> > > > hg hg hg hg merge -t "internal:merge" # does the best it can automatically resolve -l # shows merge state resolve FILE # runs conflict resolving for specific file resolve -a # runs conflict resolving for all unresolved files

IMPORTANT: Unfortunately, resolve command doesnt save progress when interrupted. There is an issue for that: http://bz.selenic.com/show_bug.cgi?id=3638. Possible workaround: iterate through conicts and call resolve for each le
Sergey Kishchenko (Quickoce) What every programmer should know about merging branches in Mercurial October 11, 2012 14 / 22

Merge problem: hard to understand the conict


Also known as I dont know which change is correct Why occurs?
Synchronizing rarely forgetting what was going on Merging components without component knowledge

How to prevent?
Synchronize often Spread the components knowledge among developers code cross-review

How to deal with?


Use help from those who have good component knowledge Learn how to use log (shows the history) and blame (shows who is the author of the changes) command

Sergey Kishchenko (Quickoce)

What every programmer should know about merging branches in Mercurial October 11, 2012

15 / 22

Merge problem: code was refactored


Also known as It seems the code was removed remotely so I can drop the local change (immediately eaten by velociraptor) Why occurs?
Doing the refactoring and not merging it into all branches immediately Merging refactored components without component knowledge

How to prevent?
Spread the ongoing refactoring knowledge among developers code cross-review Use early-x branch for refactoring and merge it immediately or notify everyone about it

How to deal with?


Use help from those who have good knowledge about the refactoring Use 3-way merge (check next slide) In case dierent refactoring was done in both local and remote versions, youre DOOMed :(
Sergey Kishchenko (Quickoce) What every programmer should know about merging branches in Mercurial October 11, 2012 16 / 22

Using 3-way merge for merging refactored code


1

Use 3-way merge graphical tool to see base(B), local(L) and remote(R) version of a le Lets assume refactoring was done only in remote. It means that base-local dierence is not large, its all about modifying names, adding params, issues x, etc. Base and remote dier a lot, often the remote version is completely missing, i.e., was moved to dierent le. Use log to identify what was refactoring about. E.g., you can nd the le that is a new home for the code that is missing from the R

Use log to nd refactoring changesets > hg log --follow R


4

Iterate through base-local dierences change by change and apply them to the code in a correct place In any case consider contacting those who did the refactoring for help and/or code review
What every programmer should know about merging branches in Mercurial October 11, 2012 17 / 22

Sergey Kishchenko (Quickoce)

Merge problem: non-source les conicts


Why occurs?
Modifying the resource/project le and not merging it into all branches immediately Storing user settings in the tree Synchronizing rarely Pointless modication of project les/resources

How to prevent?
Avoid pointless modication of non-source les Consider using an early-x branch for non-source le modication and merge it into all branches immediately Do not store user settings in the tree Consider storing mergeable sources instead of the non-source products

How to deal with?


Consider using a specialized tools to merge specic les In case les are not mergeable choose either local or remote version and try to reproduce all of the changes from the other version
Sergey Kishchenko (Quickoce) What every programmer should know about merging branches in Mercurial October 11, 2012 18 / 22

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-x 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 les Cross-code reviews Small self-contained changesets Writing easy understandable code!
Sergey Kishchenko (Quickoce) What every programmer should know about merging branches in Mercurial October 11, 2012 19 / 22

One more time: bad things

Manual merges Applying patches manually Being a coward and selecting either local or remote version without checking it Trusting automatic merge tools completely Using bad names for branches Using --force ag Copying and moving les without using hg cp/hg mv

Sergey Kishchenko (Quickoce)

What every programmer should know about merging branches in Mercurial October 11, 2012

20 / 22

One more time: things to avoid

Doing a refactoring that cant be merged into all branches immediately Modifying non-source le without merging it into all branches immediately Modifying a component that somebody is working on without notifying 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 (Quickoce)

What every programmer should know about merging branches in Mercurial October 11, 2012

21 / 22

Thank you! Questions?

Sergey Kishchenko (Quickoce)

What every programmer should know about merging branches in Mercurial October 11, 2012

22 / 22