Annotation of wikisrc/users/dholland/hgnb.mdwn, revision 1.2

1.1       dholland    1: ## Mercurial usage for NetBSD
                      2: (hypothetically assuming the repositories have been converted)
                      4: Here are some directions for how one would use Mercurial after a
                      5: NetBSD transition from CVS to Mercurial.
                      6: Most of this is pretty trivial (especially for anyone who's used
                      7: Mercurial before...)
                      9: There is a lot of FUD circulating about using a distributed version
                     10: control system, what with talk of "workflows" and "topic branches" and
                     11: other unfamiliar terms.
                     12: Most of this arises from git user communities and git advocates;
                     13: because git is screwy, using git is more complicated than using other
                     14: better designed tools.
                     15: Also, those suffering from Stockholm syndrome with respect to git tend
                     16: to believe that the complexities of git are inherent to distributed
                     17: version control, which is not the case; and many other people have been
                     18: alarmed (or scared, or confused) by things such people have told them.
                     20: ### Basic usage
                     22: First, NetBSD will go on using a central master repository. There is
                     23: nothing to be gained by changing this; we have the project
                     24: infrastructure to support it, and ultimately there has to be some tree
                     25: somewhere that constitutes the master copy regardless.
                     27: Therefore, the basic usage is almost entirely unchanged:
1.2     ! dholland   29:        CVS                     | Mercurial
1.1       dholland   30: 
1.2     ! dholland   31:        cvs checkout            | hg clone
        !            32:        cvs update -dP          | hg pull && hg update
        !            33:        cvs -n update           | hg status
        !            34:        cvs log file            | hg log file  [or just hg log]
1.1       dholland   35:        cvs update -p file      hg cat file
                     36:        cvs annotate            hg annotate
                     37:        cvs diff -u             hg diff
                     38:        cvs add                 hg add
                     39:        cvs rm                  hg rm
                     40:        [no can do]             hg cp
                     41:        [no can do]             hg mv
                     42:        cvs commit              hg commit && hg push
                     43:        cvs tag                 hg tag
                     45: You will notice that CVS's update and commit have been divided into
                     46: two now-separable actions: in Mercurial, pull fetches changes from a
                     47: remote repository but doesn't affect your working tree, and update
                     48: updates your working tree to (by default) the latest new changes.
                     49: Similarly, commit integrates changes from your working tree, but
                     50: locally only; push publishes those changes to the remote repository.
                     52: This means that you can commit many times before pushing; this is
                     53: often desirable if you're working on something nontrivial and you want
                     54: to wait until it's ready before shipping it out.
                     56: There is one catch, which is that other people can commit (and push to
                     57: the master repository) while you're working. You can mostly avoid
                     58: this, if you haven't committed anything locally yet, by doing "hg pull
                     59: && hg update" before committing, which will merge into your
                     60: uncommitted changes and works exactly like updating before committing
                     61: in CVS. However, if you've committed a number of changes, or someone
                     62: got a new change in right between when you last pulled and when you
                     63: committed, you need to do an explicit merge instead, and then you can
                     64: push.
                     66: In the simple case, you do an explicit merge as follows:
                     67:                                hg pull
                     68:                                hg merge
                     69:                                hg commit
                     71: When you get a merge conflict, you first need to resolve it (in the
                     72: usual way by editing) and then you must tag it resolved in hg before
                     73: hg will let you commit, like this:
                     74:                                hg resolve -m file
                     76: You can list unresolved conflicts thus:
                     77:                                hg resolve -l
                     79: Note that even with the explicit merge this is almost exactly
                     80: equivalent to the CVS behavior when someone commits ahead of you.
                     81: The chief difference is that because Mercurial does whole-tree
                     82: commits, *any* change ahead of you needs to be merged, not just one
                     83: that touches the same files you've edited.
                     85: There is one gotcha, which is that you can't do explicit merges in a
                     86: tree with uncommitted changes. The best way around this is to stash
                     87: your changes:
                     88:                                hg stash
                     89:                                hg merge
                     90:                                ...whatever merge stuff...
                     91:                                hg unstash
                     93: You can also do the merge in another tree; because Mercurial is a
                     94: distributed tool, you can create a temporary copy of your tree, or
                     95: push the changes you need to another tree you already have, do the
                     96: work there, and push the results back. Let's suppose you have two
                     97: trees, "src" and "scratch", where you never keep uncommitted changes
                     98: in "scratch" so it can be used for this kind of thing. Then you can do
                     99: the following (starting at the top of src):
                    101:                                hg push ../scratch
                    102:                                cd ../scratch
                    103:                                hg update
                    104:                                hg merge
                    105:                                ...whatever merge stuff, including commit...
                    106:                                cd ../src
                    107:                                hg pull ../scratch
                    108:                                hg update
                    110: ### Disconnected operation
                    112: Mercurial is a distributed system, and works by cloning the entire
                    113: history into each tree you create.
                    114: This has its downsides; but it means that you get disconnected
                    115: operation for free.
                    116: The only operations that need to contact the master repository are
                    117: push, pull, incoming, and outgoing.
                    119: ### Some other bits
                    121: A commit with no descendents (that is, the most recent commit on any
                    122: line of development) is called a "head".
                    123: You can list these as follows:
                    124:                                hg heads
                    126: This will include commits that have descendents only on other
                    127: branches, e.g. the last commit on a development branch that's been
                    128: merged but not closed. Use "-t" ("topological heads") to hide these.
                    130: You can see what "hg pull" and "hg push" are going to do via "hg
                    131: incoming" and "hg outgoing" respectively.
                    132: (FWIW, git can't do this.)
                    134: If you interrupt Mercurial (or Mercurial gets interrupted, e.g. by a
                    135: system crash) you want to do this afterwards:
                    136:                                hg recover
                    138: and if you have reason to think the repository might be corrupt you
                    139: can check it like this:
                    140:                                hg verify
                    142: ### Development branches
                    144: A development branch is one where you're working on some new feature
                    145: and you expect to merge the branch into the trunk later.
                    146: Unlike in CVS, this is very cheap in Mercurial.
                    147: The following are the operations you need, using "libc13" as an
                    148: example branch name.
                    150: Note that even if you're working on something nontrivial that will
                    151: take a number of commits, if you aren't intending to push the changes
                    152: out before they're done you don't need to make a branch and there's
                    153: nothing gained by doing so.
                    154: However, if you expect to be working over a long period of time on a
                    155: major effort (such as the mythical libc version bump), and/or you
                    156: want or expect other developers to contribute or at least test your
                    157: changes before they're done, go ahead and create a branch.
                    159: Create a new branch:
                    161:        cvs update -dP          hg pull && hg update    (if needed)
                    162:        update doc/BRANCHES     update doc/BRANCHES     (if appropriate)
                    163:        cvs commit doc/BRANCHES hg commit doc/BRANCHES  (if needed)
                    164:        cvs tag libc13-base     hg tag libc13-base
                    165:        cvs ph'tagn             hg branch libc13
                    166:        [make first change]     [make first change]
                    167:        cvs commit              hg commit
                    168:                                hg push
                    170: Mercurial warns you that branches are permanent and expensive; this
                    171: warning is aimed at git users who ought to be creating bookmarks
                    172: instead and not something you need to be concerned about.
                    174: Check out a new tree on a branch:
                    175:        cvs co -P -rlibc13      hg clone [url]
                    176:                                cd src
                    177:                                hg update -r libc13
                    179: Switch to a new tree on a branch:
                    180:        cvs up -dP -A -rlibc13  hg pull                 (if needed)
                    181:                                hg update -r libc13
                    183: Note that if you have uncommitted changes, Mercurial will balk at
                    184: crossing from one branch to another because it doesn't know how to
                    185: merge them.
                    186: In that case do this:
                    187:                                hg update -r libc13-base
                    188:                                [resolve conflicts if needed]
                    189:                                hg update -r libc13
                    190:                                [resolve conflicts if needed]
                    192: Check which branch you're currently on:
                    194:        cat CVS/Tag             hg branch
                    196: See list of branches:
                    197:        [no can do reliably]    hg branches     
                    199: Note that unlike with CVS there's no version-control-related reason to
                    200: get a new tree just to work on a branch.
                    201: (Although of course it's still possible to commit to the wrong branch
                    202: by accident.)
                    203: Get a new tree if and only if you want to have a different tree for
                    204: administrative reasons.
                    206: Sync your branch with the trunk ("HEAD" in CVS):
                    208:        cvs ph'tagn             hg merge default
                    209:        [resolve conflicts]     [resolve conflicts]
                    210:        cvs commit              hg commit
                    211:                                hg push
                    213: When you're done with your branch, in Mercurial you can "close" it so
                    214: it's no longer active.
                    215: This causes it to disappear from some reports, reduces some internal
                    216: management overheads, and prevents accidental commits on it.
                    218:        [no can do]             hg commit --close-branch
                    220: Don't forget to update doc/BRANCHES too.
                    222: ### Vendor branches
                    224: A vendor branch is one where code from a third party is committed in
                    225: unmodified state, so it can be updated easily from upstream later.
                    227: Note that in CVS vendor branches are magic (in a bad way); in
                    228: Mercurial we'll just use an ordinary branch. We'll start it from the
                    229: empty revision so it doesn't contain any unwanted rubbish.
                    231: To start a new vendor branch for the upstream package "frobozz",
                    232: assuming you've already written frobozz2netbsd if one's needed:
                    234:        mkdir tmp
                    235:        cd tmp
                    236:                                hg update -r0000
                    237:                                mkdir external && cd external
                    238:                                mkdir bsd && cd bsd
                    239:                                mkdir frobozz && cd frobozz
                    240:        tar -xvzf \             tar -xvzf \
                    241:          frobozz-1.0.tgz         frobozz-1.0.tgz
                    242:        mv frobozz-1.0 dist     mv frobozz-1.0 dist
                    243:        cp .../frobozz2netbsd . cp .../frobozz2netbsd .
                    244:        ./frobozz2netbsd        ./frobozz2netbsd        (if needed)
                    245:        cvs import \
                    246:          src/distrib/bsd/frobozz \
                    247:          FROBOZZ frobozz-1-0
                    248:                                hg add
                    249:                                hg branch FROBOZZ
                    250:                                hg commit
                    251:                                hg tag frobozz-1-0
                    252:        cd ../src
                    253:        cvs update -dP
                    254:                                hg update -r default
                    255:                                hg merge FROBOZZ
                    256:                                hg commit
                    257:        [hack as needed]        [hack as needed]
                    258:        cvs commit              hg commit
                    259:                                hg push
                    260:        cd ..
                    261:        rm -r tmp
                    263: Note that in both cases this imports frobozz2netbsd on the branch;
                    264: this seems the most convenient but I'm not sure if it's been our
                    265: standard procedure.
                    267: To update "frobozz" to 1.1:
                    269:        mkdir tmp
                    270:        cd tmp
                    271:                                hg update -rFROBOZZ
                    272:                                cd external/bsd/frobozz
                    273:        tar -xvzf \             tar -xvzf \
                    274:          frobozz-1.1.tgz         frobozz-1.1.tgz
                    275:                                rm -r dist
                    276:        mv frobozz-1.1 dist     mv frobozz-1.1 dist
                    277:        ./frobozz2netbsd        ./frobozz2netbsd
                    278:        cvs import \
                    279:          src/distrib/bsd/frobozz \
                    280:          FROBOZZ frobozz-1-0
                    281:                                hg addremove
                    282:                                hg commit
                    283:                                hg tag frobozz-1-1
                    284:        cd ..
                    285:        mkdir tmp2 && cd tmp2
                    286:        cvs ph'tagn
                    287:                                hg update -r default
                    288:                                hg merge FROBOZZ
                    289:        [resolve conflicts]     [resolve conflicts]
                    290:        cvs commit              hg commit
                    291:        cd ../src
                    292:        cvs update -dP
                    293:        [hack as needed]        [hack as needed]
                    294:        cvs commit              hg commit
                    295:                                hg push
                    296:        cd ..
                    297:        rm -r tmp tmp2
                    299: ### Release branches
                    301: A release branch is one that diverges from the main branch and is not
                    302: expected to be merged back into it.
                    303: However, changes from the main branch are (individually) merged into
                    304: it after review.
                    306: Creating a release branch in Mercurial is the same as creating a
                    307: feature branch; see above.
                    308: So is checking it out.
                    309: Committing a change to a release branch is no different from
                    310: committing to the default branch or any other branch.
                    312: TODO: we should probably use the Mercurial cherrypick extension for at
                    313: least some release branch pullups; I don't know how to do that offhand
                    314: without looking it up.
                    316: Tagging a release:
                    318:        cvs rtag -r netbsd-7 \  hg tag -r netbsd-7 \
                    319:          netbsd-7-0-RELEASE      netbsd-7-0-RELEASE
                    321: Viewing the changes on a branch:
                    323:        cvs log > file          hg log -b netbsd-7
                    324:        [page through & curse]
                    326: Extracting tarballs:
                    328:                                cd src
                    329:        hg export -r \          hg archive -r \
                    330:          netbsd-7-0-RELEASE \    netbsd-7-0-RELEASE \
                    331:          src                     .../netbsd-7.0.tar.gz
                    332:        mv src netbsd-7.0
                    333:        tar -cvzf \
                    334:          netbsd-7.0.tar.gz \
                    335:          netbsd-7.0
                    337: ### Reverting a bad commit
                    339: Sometimes somebody commits something that needs to be unwound later.
                    340: In CVS you have to track down each per-file change and undo each one
                    341: separately, then commit them all.
                    342: In Mercurial, because Mercurial has whole-tree commits, you can do it
                    343: with a single command.
                    345:        cvs update -j1.6 -j1.5 foo.c
                    346:        cvs update -j1.9 -j1.8 bar.c
                    347:        cvs update -j1.15 -j1.14 baz.c
                    348:                                hg backout -r 101abcde
                    349:        [resolve conflicts]     [resolve conflicts]
                    350:        cvs commit              hg commit
                    351:                                hg push
                    353: Note that apparently if you use hg backout to back out the most recent
                    354: commit, it auto-commits.
                    355: (This seems to me like a UI bug.)
                    357: ### Carrying local changes
                    359: In CVS you can keep uncommitted changes in your tree indefinitely with
                    360: no ill effects.
                    361: (Or at least, no ill effects until you want to commit other changes to
                    362: the same files, run into merge conflicts, or hit PR 42961.)
                    364: In Mercurial having uncommitted changes keeps you from doing explicit
                    365: merges, which you need to do much more often than in CVS.
                    366: There are several ways around this:
                    368: * You can stash your uncommitted changes any time you need to merge.
                    369: This works fine but it quickly becomes a nuisance.
                    370: * You can use different trees for hacking and for building the system
                    371: for install, since presumably you only need the local changes in
                    372: the latter case.
                    373: This works fine until you need to shift partially-completed hacking to
                    374: the installable tree, and then becomes painful.
                    375: * You can commit your local changes as "secret" using the evolve
                    376: extension (I recommend reading the docs for the evolve extension);
                    377: then they're committed and can be merged and so on, but won't get
                    378: pushed back to the master repository.
                    379: The downside of this is that you can't readily distribute your local
                    380: changes among your own repositories.
                    381: * You can use the mq patch queue extension and store your local
                    382: changes as patches against the tree; then they can be popped off
                    383: easily for other work.
                    384: The downside of this is that merging stuff into your local changes
                    385: becomes awkward.
                    386: * You can finish your local changes so they can be committed upstream :-)
                    388: None of these solutions is perfect, but one or the other of these
                    389: approaches is probably good enough in most cases.
                    391: ### Reverting stuff locally
                    393: In CVS you can use "cvs update" to pin a subtree down to a specific
                    394: point in history, where it will stay while you update the rest of the
                    395: tree around it.
                    396: (Accidental engagement of this feature is probably as common as
                    397: intentional use...)
                    399: There is no direct equivalent in Mercurial.
                    400: However, you can easily alter a file or subtree to roll it back to a
                    401: specific point in history, and then carry the resulting diff as a
                    402: local modification until whatever issue prompted you to do this gets
                    403: sorted out.
                    405: To revert to a specific version:
                    406:                                hg revert -r rev subtree
                    407: To revert to a specific date:
                    408:                                hg revert -d date subtree
                    411: ### Other stuff
                    413: Have I forgotten anything?
                    414: Email me questions...

CVSweb for NetBSD wikisrc <> software: FreeBSD-CVSweb