Upload
sergey-kishchenko
View
2.835
Download
0
Embed Size (px)
DESCRIPTION
Slides for a talk on merging branches in Mercurial that I did on Oct 11, 2012 at Quickoffice
Citation preview
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Thank you! Questions?
Sergey Kishchenko (Quickoffice) What every programmer should know about merging branches in MercurialOctober 11, 2012 22 / 22