Annotation of wikisrc/users/dholland/hgnb.mdwn, revision 1.6
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:
1.6 ! dholland 29: CVS Mercurial
1.3 dholland 30:
1.6 ! 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]
! 35:
! 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.
52:
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.
56:
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
65: push.
66:
67: In the simple case, you do an explicit merge as follows:
68: hg pull
69: hg merge
70: hg commit
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:
75: hg resolve -m file
76:
77: You can list unresolved conflicts thus:
78: hg resolve -l
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.
85:
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
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):
101:
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
110:
111: ### Disconnected operation
112:
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.
119:
120: ### Some other bits
121:
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
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.
130:
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.)
134:
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
138:
139: and if you have reason to think the repository might be corrupt you
140: can check it like this:
141: hg verify
142:
143: ### Development branches
144:
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.
150:
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.
159:
160: Create a new branch:
161:
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
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.
174:
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
179:
180: Switch to a new tree on a branch:
181: cvs up -dP -A -rlibc13 hg pull (if needed)
182: hg update -r libc13
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:
188: hg update -r libc13-base
189: [resolve conflicts if needed]
190: hg update -r libc13
191: [resolve conflicts if needed]
192:
193: Check which branch you're currently on:
194:
195: cat CVS/Tag hg branch
196:
197: See list of branches:
198: [no can do reliably] hg branches
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.
206:
207: Sync your branch with the trunk ("HEAD" in CVS):
208:
209: cvs ph'tagn hg merge default
210: [resolve conflicts] [resolve conflicts]
211: cvs commit hg commit
212: hg push
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.
218:
219: [no can do] hg commit --close-branch
220:
221: Don't forget to update doc/BRANCHES too.
222:
223: ### Vendor branches
224:
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.
227:
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.
231:
232: To start a new vendor branch for the upstream package "frobozz",
233: assuming you've already written frobozz2netbsd if one's needed:
234:
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 \ tar -xvzf \
242: frobozz-1.0.tgz 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 \
247: src/distrib/bsd/frobozz \
248: FROBOZZ frobozz-1-0
249: hg add
250: hg branch FROBOZZ
251: hg commit
252: hg tag frobozz-1-0
253: cd ../src
254: cvs update -dP
255: hg update -r default
256: hg merge FROBOZZ
257: hg commit
258: [hack as needed] [hack as needed]
259: cvs commit hg commit
260: hg push
261: cd ..
262: rm -r tmp
263:
264: Note that in both cases this imports frobozz2netbsd on the branch;
265: this seems the most convenient but I'm not sure if it's been our
266: standard procedure.
267:
268: To update "frobozz" to 1.1:
269:
270: mkdir tmp
271: cd tmp
272: hg update -rFROBOZZ
273: cd external/bsd/frobozz
274: tar -xvzf \ tar -xvzf \
275: frobozz-1.1.tgz frobozz-1.1.tgz
276: rm -r dist
277: mv frobozz-1.1 dist mv frobozz-1.1 dist
278: ./frobozz2netbsd ./frobozz2netbsd
279: cvs import \
280: src/distrib/bsd/frobozz \
281: FROBOZZ frobozz-1-0
282: hg addremove
283: hg commit
284: hg tag frobozz-1-1
285: cd ..
286: mkdir tmp2 && cd tmp2
287: cvs ph'tagn
288: hg update -r default
289: hg merge FROBOZZ
290: [resolve conflicts] [resolve conflicts]
291: cvs commit hg commit
292: cd ../src
293: cvs update -dP
294: [hack as needed] [hack as needed]
295: cvs commit hg commit
296: hg push
297: cd ..
298: rm -r tmp tmp2
299:
300: ### Release branches
301:
302: A release branch is one that diverges from the main branch and is not
303: expected to be merged back into it.
304: However, changes from the main branch are (individually) merged into
305: it after review.
306:
307: Creating a release branch in Mercurial is the same as creating a
308: feature branch; see above.
309: So is checking it out.
310: Committing a change to a release branch is no different from
311: committing to the default branch or any other branch.
312:
313: TODO: we should probably use the Mercurial cherrypick extension for at
314: least some release branch pullups; I don't know how to do that offhand
315: without looking it up.
316:
317: Tagging a release:
318:
319: cvs rtag -r netbsd-7 \ hg tag -r netbsd-7 \
320: netbsd-7-0-RELEASE netbsd-7-0-RELEASE
321:
322: Viewing the changes on a branch:
323:
324: cvs log > file hg log -b netbsd-7
325: [page through & curse]
326:
327: Extracting tarballs:
328:
329: cd src
330: hg export -r \ hg archive -r \
331: netbsd-7-0-RELEASE \ netbsd-7-0-RELEASE \
332: src .../netbsd-7.0.tar.gz
333: mv src netbsd-7.0
334: tar -cvzf \
335: netbsd-7.0.tar.gz \
336: netbsd-7.0
337:
338: ### Reverting a bad commit
339:
340: Sometimes somebody commits something that needs to be unwound later.
341: In CVS you have to track down each per-file change and undo each one
342: separately, then commit them all.
343: In Mercurial, because Mercurial has whole-tree commits, you can do it
344: with a single command.
345:
346: cvs update -j1.6 -j1.5 foo.c
347: cvs update -j1.9 -j1.8 bar.c
348: cvs update -j1.15 -j1.14 baz.c
349: hg backout -r 101abcde
350: [resolve conflicts] [resolve conflicts]
351: cvs commit hg commit
352: hg push
353:
354: Note that apparently if you use hg backout to back out the most recent
355: commit, it auto-commits.
356: (This seems to me like a UI bug.)
357:
358: ### Carrying local changes
359:
360: In CVS you can keep uncommitted changes in your tree indefinitely with
361: no ill effects.
362: (Or at least, no ill effects until you want to commit other changes to
363: the same files, run into merge conflicts, or hit PR 42961.)
364:
365: In Mercurial having uncommitted changes keeps you from doing explicit
366: merges, which you need to do much more often than in CVS.
367: There are several ways around this:
368:
369: * You can stash your uncommitted changes any time you need to merge.
370: This works fine but it quickly becomes a nuisance.
371: * You can use different trees for hacking and for building the system
372: for install, since presumably you only need the local changes in
373: the latter case.
374: This works fine until you need to shift partially-completed hacking to
375: the installable tree, and then becomes painful.
376: * You can commit your local changes as "secret" using the evolve
377: extension (I recommend reading the docs for the evolve extension);
378: then they're committed and can be merged and so on, but won't get
379: pushed back to the master repository.
380: The downside of this is that you can't readily distribute your local
381: changes among your own repositories.
382: * You can use the mq patch queue extension and store your local
383: changes as patches against the tree; then they can be popped off
384: easily for other work.
385: The downside of this is that merging stuff into your local changes
386: becomes awkward.
387: * You can finish your local changes so they can be committed upstream :-)
388:
389: None of these solutions is perfect, but one or the other of these
390: approaches is probably good enough in most cases.
391:
392: ### Reverting stuff locally
393:
394: In CVS you can use "cvs update" to pin a subtree down to a specific
395: point in history, where it will stay while you update the rest of the
396: tree around it.
397: (Accidental engagement of this feature is probably as common as
398: intentional use...)
399:
400: There is no direct equivalent in Mercurial.
401: However, you can easily alter a file or subtree to roll it back to a
402: specific point in history, and then carry the resulting diff as a
403: local modification until whatever issue prompted you to do this gets
404: sorted out.
405:
406: To revert to a specific version:
407: hg revert -r rev subtree
408: To revert to a specific date:
409: hg revert -d date subtree
410:
411:
412: ### Other stuff
413:
414: Have I forgotten anything?
415: Email me questions...
CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb