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:
199: [no can do reliably] hg branches
201: Note that unlike with CVS there's no version-control-related reason to
202: get a new tree just to work on a branch.
203: (Although of course it's still possible to commit to the wrong branch
204: by accident.)
205: Get a new tree if and only if you want to have a different tree for
206: administrative reasons.
208: Sync your branch with the trunk ("HEAD" in CVS):
210: cvs ph'tagn hg merge default
211: [resolve conflicts] [resolve conflicts]
212: cvs commit hg commit
213: hg push
215: When you're done with your branch, in Mercurial you can "close" it so
216: it's no longer active.
217: This causes it to disappear from some reports, reduces some internal
218: management overheads, and prevents accidental commits on it.
220: [no can do] hg commit --close-branch
222: Don't forget to update doc/BRANCHES too.
224: ### Vendor branches
226: A vendor branch is one where code from a third party is committed in
227: unmodified state, so it can be updated easily from upstream later.
229: Note that in CVS vendor branches are magic (in a bad way); in
230: Mercurial we'll just use an ordinary branch. We'll start it from the
231: empty revision so it doesn't contain any unwanted rubbish.
233: To start a new vendor branch for the upstream package "frobozz",
234: assuming you've already written frobozz2netbsd if one's needed:
236: mkdir tmp
237: cd tmp
238: hg update -r0000
239: mkdir external && cd external
240: mkdir bsd && cd bsd
241: mkdir frobozz && cd frobozz
242: tar -xvzf frobozz-1.0.tgz tar -xvzf frobozz-1.0.tgz
243: mv frobozz-1.0 dist mv frobozz-1.0 dist
244: cp .../frobozz2netbsd . cp .../frobozz2netbsd .
245: ./frobozz2netbsd ./frobozz2netbsd (if needed)
246: cvs import 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
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.
267: To update "frobozz" to 1.1:
269: mkdir tmp
270: cd tmp
271: hg update -rFROBOZZ
272: cd external/bsd/frobozz
273: tar -xvzf frobozz-1.1.tgz tar -xvzf frobozz-1.1.tgz
274: rm -r dist
275: mv frobozz-1.1 dist mv frobozz-1.1 dist
276: ./frobozz2netbsd ./frobozz2netbsd
277: cvs import src/distrib/bsd/frobozz \
278: FROBOZZ frobozz-1-0
279: hg addremove
280: hg commit
281: hg tag frobozz-1-1
282: cd ..
283: mkdir tmp2 && cd tmp2
284: cvs ph'tagn
285: hg update -r default
286: hg merge FROBOZZ
287: [resolve conflicts] [resolve conflicts]
288: cvs commit hg commit
289: cd ../src
290: cvs update -dP
291: [hack as needed] [hack as needed]
292: cvs commit hg commit
293: hg push
294: cd ..
295: rm -r tmp tmp2
297: ### Release branches
299: A release branch is one that diverges from the main branch and is not
300: expected to be merged back into it.
301: However, changes from the main branch are (individually) merged into
302: it after review.
304: Creating a release branch in Mercurial is the same as creating a
305: feature branch; see above.
306: So is checking it out.
307: Committing a change to a release branch is no different from
308: committing to the default branch or any other branch.
310: TODO: we should probably use the Mercurial cherrypick extension for at
311: least some release branch pullups; I don't know how to do that offhand
312: without looking it up.
314: Tagging a release:
316: cvs rtag -r netbsd-7 \ hg tag -r netbsd-7 \
317: netbsd-7-0-RELEASE netbsd-7-0-RELEASE
319: Viewing the changes on a branch:
321: cvs log > file hg log -b netbsd-7
322: [page through and curse]
324: Extracting tarballs:
326: mkdir tmp
327: cd tmp
328: cvs export -r netbsd-7-0-RELEASE \ hg archive -r netbsd-7-0-RELEASE \
329: src ../netbsd-7.0.tar.gz
330: mv src netbsd-7.0
331: tar -cvzf ../netbsd-7.0.tar.gz \
333: cd ..
334: rm -r tmp
337: ### Reverting a bad commit
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.
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
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.)
357: ### Carrying local changes
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.)
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:
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 :-)
388: None of these solutions is perfect, but one or the other of these
389: approaches is probably good enough in most cases.
391: ### Reverting stuff locally
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...)
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.
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
411: ### Other stuff
413: Have I forgotten anything?
414: Email me questions...
CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb