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