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:
29: CVS Mercurial
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
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:
68: hg pull
69: hg merge
70: hg commit
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:
75: hg resolve -m file
77: You can list unresolved conflicts thus:
78: hg resolve -l
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:
89: hg stash
90: hg merge
91: ...whatever merge stuff...
92: hg unstash
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):
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
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:
125: hg heads
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:
137: hg recover
139: and if you have reason to think the repository might be corrupt you
140: can check it like this:
141: hg verify
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:
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
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:
176: cvs co -P -rlibc13 hg clone [url]
177: cd src
178: hg update -r libc13
180: Switch to a new tree on a branch:
181: cvs up -dP -A -rlibc13 hg pull (if needed)
182: hg update -r libc13
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:
188: hg update -r libc13-base
189: [resolve conflicts if needed]
190: hg update -r libc13
191: [resolve conflicts if needed]
193: Check which branch you're currently on:
195: cat CVS/Tag hg branch
197: See list of branches:
198: [no can do reliably] hg branches
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):
209: cvs ph'tagn hg merge default
210: [resolve conflicts] [resolve conflicts]
211: cvs commit hg commit
212: hg push
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.
219: [no can do] hg commit --close-branch
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:
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
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:
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
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:
315: cvs rtag -r netbsd-7 \ hg tag -r netbsd-7 \
316: netbsd-7-0-RELEASE netbsd-7-0-RELEASE
318: Viewing the changes on a branch:
320: cvs log > file hg log -b netbsd-7
321: [page through and curse]
323: Extracting tarballs:
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 \
332: cd ..
333: rm -r tmp
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.
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
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:
405: hg revert -r rev subtree
406: To revert to a specific date:
407: hg revert -d date subtree
410: ### Other stuff
412: Have I forgotten anything?
413: Email me questions...
CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb