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

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

CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb