Annotation of wikisrc/users/dholland/hgnb.mdwn, revision 1.1
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:
! 29: CVS Mercurial
! 30:
! 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: 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
! 44:
! 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.
! 51:
! 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.
! 55:
! 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.
! 65:
! 66: In the simple case, you do an explicit merge as follows:
! 67: hg pull
! 68: hg merge
! 69: hg commit
! 70:
! 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
! 75:
! 76: You can list unresolved conflicts thus:
! 77: hg resolve -l
! 78:
! 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.
! 84:
! 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
! 92:
! 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):
! 100:
! 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
! 109:
! 110: ### Disconnected operation
! 111:
! 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.
! 118:
! 119: ### Some other bits
! 120:
! 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
! 125:
! 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.
! 129:
! 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.)
! 133:
! 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
! 137:
! 138: and if you have reason to think the repository might be corrupt you
! 139: can check it like this:
! 140: hg verify
! 141:
! 142: ### Development branches
! 143:
! 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.
! 149:
! 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.
! 158:
! 159: Create a new branch:
! 160:
! 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
! 169:
! 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.
! 173:
! 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
! 178:
! 179: Switch to a new tree on a branch:
! 180: cvs up -dP -A -rlibc13 hg pull (if needed)
! 181: hg update -r libc13
! 182:
! 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]
! 191:
! 192: Check which branch you're currently on:
! 193:
! 194: cat CVS/Tag hg branch
! 195:
! 196: See list of branches:
! 197: [no can do reliably] hg branches
! 198:
! 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.
! 205:
! 206: Sync your branch with the trunk ("HEAD" in CVS):
! 207:
! 208: cvs ph'tagn hg merge default
! 209: [resolve conflicts] [resolve conflicts]
! 210: cvs commit hg commit
! 211: hg push
! 212:
! 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.
! 217:
! 218: [no can do] hg commit --close-branch
! 219:
! 220: Don't forget to update doc/BRANCHES too.
! 221:
! 222: ### Vendor branches
! 223:
! 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.
! 226:
! 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.
! 230:
! 231: To start a new vendor branch for the upstream package "frobozz",
! 232: assuming you've already written frobozz2netbsd if one's needed:
! 233:
! 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
! 262:
! 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.
! 266:
! 267: To update "frobozz" to 1.1:
! 268:
! 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
! 298:
! 299: ### Release branches
! 300:
! 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.
! 305:
! 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.
! 311:
! 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.
! 315:
! 316: Tagging a release:
! 317:
! 318: cvs rtag -r netbsd-7 \ hg tag -r netbsd-7 \
! 319: netbsd-7-0-RELEASE netbsd-7-0-RELEASE
! 320:
! 321: Viewing the changes on a branch:
! 322:
! 323: cvs log > file hg log -b netbsd-7
! 324: [page through & curse]
! 325:
! 326: Extracting tarballs:
! 327:
! 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
! 336:
! 337: ### Reverting a bad commit
! 338:
! 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.
! 344:
! 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
! 352:
! 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.)
! 356:
! 357: ### Carrying local changes
! 358:
! 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.)
! 363:
! 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:
! 367:
! 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 :-)
! 387:
! 388: None of these solutions is perfect, but one or the other of these
! 389: approaches is probably good enough in most cases.
! 390:
! 391: ### Reverting stuff locally
! 392:
! 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...)
! 398:
! 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.
! 404:
! 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
! 409:
! 410:
! 411: ### Other stuff
! 412:
! 413: Have I forgotten anything?
! 414: Email me questions...
CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb