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:
69: hg pull
70: hg merge
71: hg commit
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:
77: hg resolve -m file
79: You can list unresolved conflicts thus:
81: hg resolve -l
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.
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:
93: hg stash
94: hg merge
95: ...whatever merge stuff...
96: hg unstash
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):
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
115: ### Disconnected operation
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.
124: ### Some other bits
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:
130: hg heads
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.
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.)
140: If you interrupt Mercurial (or Mercurial gets interrupted, e.g. by a
141: system crash) you want to do this afterwards:
143: hg recover
145: and if you have reason to think the repository might be corrupt you
146: can check it like this:
148: hg verify
150: ### Development branches
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.
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.
167: Create a new branch:
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
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.
182: Check out a new tree on a branch:
184: cvs co -P -rlibc13 hg clone [url]
185: cd src
186: hg update -r libc13
188: Switch to a new tree on a branch:
190: cvs up -dP -A -rlibc13 hg pull (if needed)
191: hg update -r libc13
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:
198: hg update -r libc13-base
199: [resolve conflicts if needed]
200: hg update -r libc13
201: [resolve conflicts if needed]
203: Check which branch you're currently on:
205: cat CVS/Tag hg branch
207: See list of branches:
209: [no can do reliably] hg branches
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.
218: Sync your branch with the trunk ("HEAD" in CVS):
220: cvs ph'tagn hg merge default
221: [resolve conflicts] [resolve conflicts]
222: cvs commit hg commit
223: hg push
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.
230: [no can do] hg commit --close-branch
232: Don't forget to update doc/BRANCHES too.
234: ### Vendor branches
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.
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.
243: To start a new vendor branch for the upstream package "frobozz",
244: assuming you've already written frobozz2netbsd if one's needed:
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
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.
277: To update "frobozz" to 1.1:
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
307: ### Release branches
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.
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.
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.
324: Tagging a release:
326: cvs rtag -r netbsd-7 \ hg tag -r netbsd-7 \
327: netbsd-7-0-RELEASE netbsd-7-0-RELEASE
329: Viewing the changes on a branch:
331: cvs log > file hg log -b netbsd-7
332: [page through and curse]
334: Extracting tarballs:
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 \
343: cd ..
344: rm -r tmp
347: ### Reverting a bad commit
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.
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
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.)
367: ### Carrying local changes
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.)
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:
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 :-)
398: None of these solutions is perfect, but one or the other of these
399: approaches is probably good enough in most cases.
401: ### Reverting stuff locally
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...)
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.
415: To revert to a specific version:
417: hg revert -r rev subtree
418: To revert to a specific date:
420: hg revert -d date subtree
423: ### Other stuff
425: Have I forgotten anything?
426: Email me questions...
CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb