Merge lp:~abentley/bzr/devnotes into lp:~bzr-core/bzr/devnotes

Proposed by Aaron Bentley
Status: Merged
Merged at revision: not available
Proposed branch: lp:~abentley/bzr/devnotes
Merge into: lp:~bzr-core/bzr/devnotes
Diff against target: 1369 lines
To merge this branch: bzr merge lp:~abentley/bzr/devnotes
Reviewer Review Type Date Requested Status
Robert Collins (community) Abstain
Review via email: mp+8766@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Aaron Bentley (abentley) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi all,

Here's my revised documentation for nested trees. In includes all three
documents: NestedTreesDesign from the wiki, Ian's proposed userdoc, and
the devnotes/nested-trees.txt from the most recent sprint.

I have updated them to provide a coherent view of nested trees,
harmonized with the design decisions made by Andrew Bennetts and me at
the sprint.

There's quite a lot of documentation to go over, so I may have missed
some inconsistencies. Please let me know if so.

Aaron
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkpctAMACgkQ0F+nu1YWqI2HMwCeMOEG/7vmjBkUfkgRKyRsXS78
nY4An3c4AprS3bb4mSFFsCMc30cA+ueD
=uzRm
-----END PGP SIGNATURE-----

Revision history for this message
Martin Pool (mbp) wrote :
Download full text (6.3 KiB)

This looks like a really nice clear description of the plan. I'm not sure if you're looking to merge it in as an indication it's definitely agreed this is what we'll do, or if you want to merge it as a work-in-progress for the spec.

I still have some doubts about whether recursing downwards is really what people want and/or is the safest strategy for introducing the feature. Maybe once we get this document merged in you can do a specific survey of users on that point. I realize it's been discussed before but the results seem to be mixed.

+seems likely that Bazaar will one day support them file copies, and when it

s/them//

134 +The branches associated with subtrees shall be called "subbranches".
135 +
136 +The branch for the top tree will be in a special format, whose last_revision
137 +file lists all the last_revision info for all of the branches associated with
138 +the nested tree. The .bzr directories of subtrees will have a "branch" that
139 +simply indicates that the top tree's branch should be used.
140 +
141 +In the top tree's last_revision file, the revision id and revno will be
142 +provided, indexed by the tree-reference file-id.
143 +
144 +The repository used by the top-tree's branch must be a shared repository, and
145 +will be used by the sub-branches.
146

I like this better than having separate whole branch control directories.

We'll probably have colocated branches in the same timeframe as this change so we should make sure they will mesh well.

Maybe add sub-branch to the glossary at the top?

But I think we need to back up here and clarify what these branches mean. (Unless you do that later.) I think what you want is:

When you commit in a subtree, it updates the sub-branch pointer. When you run log/etc/push/pull/merge in the subtree, it also uses this pointer. When you commit in the containing tree, it writes the current values of these sub-branch pointers into the inventory for the enclosing tree.

If you're looking at an already-committed version of the containing tree, it'll find the subtrees by looking in the containing tree's inventory.

This seems to imply that the sub-branches are almost just working tree data -- if you're not interested in commits that haven't been wrapped up in a containing tree commit yet, you don't need to see them.

So would it be enough then to just have plain trees with branches in there?

Presumably this adds a constraint on repositories (or clarifies a constraint) that a repository that contains a nested tree revision should hold all the data needed for the subtrees.

202 +Implementation strategies
203 +*************************
204 +

It's not clear here if you're going to describe several alternative implementation strategies...

230 +The obvious way to prevent slowness when there are no subtrees is to provide a
231 +fast way of determining whether there are subtrees. This could be provided by
232 +additional on-disk indices, or potentially by providing a flag indicating
233 +whether there are subtrees. Such a flag could be updated by Tree.iter_entries,
234 +to avoid re-running Tree.iter_entries. A parallel flag for iter_changes is
235 +also conceivable, but would be more com...

Read more...

Revision history for this message
Aaron Bentley (abentley) wrote :
Download full text (8.0 KiB)

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Martin Pool wrote:
> This looks like a really nice clear description of the plan. I'm not sure if you're looking to merge it in as an indication it's definitely agreed this is what we'll do,

Yes.

> I still have some doubts about whether recursing downwards is really what people want and/or is the safest strategy for introducing the feature. Maybe once we get this document merged in you can do a specific survey of users on that point. I realize it's been discussed before but the results seem to be mixed.

You have asked me to reconsider it before. The last time, I took your
advice and asked Andrew Bennets' opinion, doing my best to fairly lay
out the pros and cons of each strategy, and he chose downwards
recursion. Please accept that.

I recognize that you have doubts, but I have doubts about doing it the
other way. We've reviewed it multiple times, and each time the outcome
was downwards recursion.

> +seems likely that Bazaar will one day support them file copies, and when it
>
> s/them//
>

Fixed.

> 134 +The branches associated with subtrees shall be called "subbranches".
> 135 +
> 136 +The branch for the top tree will be in a special format, whose last_revision
> 137 +file lists all the last_revision info for all of the branches associated with
> 138 +the nested tree. The .bzr directories of subtrees will have a "branch" that
> 139 +simply indicates that the top tree's branch should be used.
> 140 +
> 141 +In the top tree's last_revision file, the revision id and revno will be
> 142 +provided, indexed by the tree-reference file-id.
> 143 +
> 144 +The repository used by the top-tree's branch must be a shared repository, and
> 145 +will be used by the sub-branches.
> 146
>
> I like this better than having separate whole branch control directories.
>
> We'll probably have colocated branches in the same timeframe as this change so we should make sure they will mesh well.
>
> Maybe add sub-branch to the glossary at the top?

Done

>
> But I think we need to back up here and clarify what these branches mean. (Unless you do that later.) I think what you want is:
>
> When you commit in a subtree, it updates the sub-branch pointer. When you run log/etc/push/pull/merge in the subtree, it also uses this pointer. When you commit in the containing tree, it writes the current values of these sub-branch pointers into the inventory for the enclosing tree.
>
> If you're looking at an already-committed version of the containing tree, it'll find the subtrees by looking in the containing tree's inventory.

Agreed.

> This seems to imply that the sub-branches are almost just working tree data -- if you're not interested in commits that haven't been wrapped up in a containing tree commit yet, you don't need to see them.
>
> So would it be enough then to just have plain trees with branches in there?

If you mean trees whose branches are in the same .bzr, that is problematic.

- - We want a guarantee that all the branches share a single repository
- - It doesn't provide synchonized control of push/pull/submit locations
- - Bzr will create or delete the branches at will, trashing any user
custo...

Read more...

lp:~abentley/bzr/devnotes updated
35. By Aaron Bentley

Updates from review

Revision history for this message
Robert Collins (lifeless) :
review: Abstain
Revision history for this message
Martin Pool (mbp) wrote :

I'll merge this into devnotes; it may need some more thought about foreign branch support but it's worth checkpointing this.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'nested-trees.txt'
--- nested-trees.txt 2009-05-29 15:50:06 +0000
+++ nested-trees.txt 2009-08-25 03:35:20 +0000
@@ -2,43 +2,121 @@
2Nested Trees2Nested Trees
3************3************
44
5.. sectnum::
6
7.. contents::
8
5Principles9Principles
6**********10**********
711
8- Never store a location in versioned data.12- Never store a location in versioned data.
913
10- Implementation of nested trees shall not make operations observably slower14- Implementation of nested trees shall not make operations observably slower
11 for those not using nested trees. (Using nested trees will impact performance15 for those not using nested trees. (Using nested trees will impact
12 in the initial implementation, but the design will allow a performant16 performance in the initial implementation, but the design will allow a
13 implementation.)17 performant implementation.)
1418
15- A repository that holds a revision R should be able to reconstruct the19- A repository that holds a revision R should be able to reconstruct the
16 whole contents of that revision, including any nested trees. Corolary:20 whole contents of that revision, including any nested trees. Corolary:
17 if I fetch that revision, even into a branch that has no working tree, it21 if I fetch that revision, even into a branch that has no working tree, it
18 should bring across any referenced revisions.22 should bring across any referenced revisions.
1923
20- A project with zero nested trees must pay zero performance cost when24Core Concepts
21 using a format supporting them.25*************
2226
23Design27**Subtree** A tree which is inside another tree, which bzr has been asked to
24******28treat as part of the outer tree.
2529
26(See also <http://bazaar-vcs.org/NestedTreesDesign>)30**Subbranch** The branch associated with a subtree.
2731
28Inventory entries of type 'tree reference' have a file-id and a revision-id.32**Containing tree** A tree which has another tree inside it
2933
30In the working tree, subtrees are represented as a subdirectory. The top34**Tree reference** A directory in a containing tree which contains a subtree.
31containing tree's branch will be in a format that contains:35
3236**Composite tree** A tree which behaves as a single tree, but is actually made
33 - the last-revision pointers for all the nested branches indexed by the file-id37up of several trees.
34 of their tree reference. 38
35 - the subbranches will use the same repository as the top tree. This39
36 repository may be at the top tree, or a shared repository used by the top40Basic design approach
37 tree.41*********************
3842(see "Design decisions" for extended rationale)
39On disk, the subtrees will simply indicate that their data is stored in a top43By default, commands in containing trees should behave as though the subtrees
40tree. The top tree for a subtree is located by walking parent dirs until a top44were plain directories. By default, commands in subtrees should not affect the
41tree is found.45containing trees.
46
47Downwards recursion
48~~~~~~~~~~~~~~~~~~~
49One of the objectives of nested trees is to provide ways of reproducing
50historical combinations of different codebases. The dependency chain points
51downwards, such that trees are affected by the revision of their subtrees, but
52subtrees are oblivious to their containing trees. Just as bazaar doesn't
53entice people to commit inconsistent trees, it should not entice people to
54commit inconsistent combinations of containing tree and subtree. Therefore,
55commit should recurse downwards by default.
56
57Status and diff should reflect what will happen when commit is used, so they
58should also recurse downward by default. Add almost does this already. With
59status, diff, commit and add recursing downwards, it would be confusing to
60users if other operations did not. Therefore, all operations should recurse
61downwards by default.
62
63No upwards recursion by default
64~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
65One of the reasons for using nested trees is to gain performance by only
66committing in a subtree. Therefore, operations should not recurse upwards by
67default. However, some users do want to have upwards recursion, so it should
68be provided as an option.
69
70Modelling nested trees as a composite tree.
71~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72The idea that a set of nested trees behaves like a single, larger tree seems
73relatively easy to grasp. Both for users and for developers, it provides a
74clear expectation for the behaviour of nested trees. There are no obvious
75drawbacks in terms of code clarity or performance. Therefore, it seems like a
76good model to start with.
77
78There are cases where users place multiple copies of a source tree inside
79another tree, and treating a set of nested trees like a single large tree is in
80conflict with that. It is essentially the same as supporting file copies, and
81file copies themselves are a big and complicated feature to implement. It
82seems likely that Bazaar will one day support file copies, and when it does,
83this conflict will disappear. Implementing limited support for copies via
84nesting would have similar complexity to implementing general support for file
85copies, but would have fewer fruits. It would lead to complication when true
86support for file copies is implemented. It does not seem appropriate for
87initial nested-tree support. On the other hand, it could be implemented later;
88none of the data model changes are in conflict with that.
89
90Using root file-ids for tree-references
91~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
92The idea that tree-reference file-ids are the same as the file-ids of the
93corresponding root directories has a nice symmetry. It is one way of ensuring
94that "bzr split" is deterministic, and "bzr join" is deterministic. When
95performing operations involving a tree and a split version of that tree, using
96the same file-id makes it easy to ensure that operations such as moves and
97renames are applied appropriately to the tree-reference. Providing mechanisms
98whereby a tree-reference can be treated as it would if it had its old file-id
99encroaches on the territory of path tokens or file-id aliases. Having "split"
100cause file-id changes means that in comparing these revisions, it would be seen
101as a deleting a directory and creating a new tree-reference with the same name.
102Handling this correctly in operations such as merge and revert would be more
103complicated than if it were treated as a kind change, especially when
104unversioned files are present in the subtree.
105
106Sub-branches
107~~~~~~~~~~~~
108The branches associated with subtrees shall be called "subbranches".
109
110The branch for the top tree will be in a special format, whose last_revision
111file lists all the last_revision info for all of the branches associated with
112the nested tree. The .bzr directories of subtrees will have a "branch" that
113simply indicates that the top tree's branch should be used.
114
115In the top tree's last_revision file, the revision id and revno will be
116provided, indexed by the tree-reference file-id.
117
118The repository used by the top-tree's branch must be a shared repository, and
119will be used by the sub-branches.
42120
43Only the top branch will have a branch.conf. When an operation on a subbranch121Only the top branch will have a branch.conf. When an operation on a subbranch
44would normally use values from branch.conf it will look them up in the top122would normally use values from branch.conf it will look them up in the top
@@ -46,25 +124,871 @@
46push" in a subtree will push just that subbranch to the corresponding subbranch124push" in a subtree will push just that subbranch to the corresponding subbranch
47in the configured push location of the top branch.125in the configured push location of the top branch.
48126
49Process127Rationale
50*******128.........
51129If the branches were not local, the local subtrees might not be committable,
52How do we best manage the risk associated with this complex feature?130and commits to the remote branch would make the local subtree out of date.
53131They should not be in a separate location from the containing branch, because
54Is it by getting something out there and planning/expecting a few132they might share history with the tree-reference's branch. However, those
55iterations to smooth out issues? Is it by taking more time before133local branches should not be at the same location as their tree, because the
56coding and landing patches to discuss the design? Or a mix of these?134tree might be deleted or moved. Indeed, they should not be anywhere within a
57135working tree.
58We need to be careful. On the one hand, we don't want to put user136
59data at risk and that's possible if the core data model (not caches)137subtree branches should not be above or beside their containing branch, because
60is flawed. On the other, we don't want to get bogged down worrying138it could cause terrible confusion if subtrees from two different trees were
61about obscure edge cases now at the expense of solving the common139updating the same branches with every push, pull, commit and uncommit.
62cases well. This feature will be a classic case of 90% of users140
63only needing 10% of the capability IMNSHO. (igc)141Subtree branches could be plain branches stored somewhere in the top tree's
64142branch, but then a lookup mechanism would be needed to translate from file_id
65143to location, and performance with large numbers of subbranches would be poor.
66Undecided questions144
67*******************145Pull and non-initial push
146~~~~~~~~~~~~~~~~~~~~~~~~~
147When a pull involves updates to tree references, pull will always pull into the
148reference branch. For all new revisions in the upper branch, it will determine
149the revision values of tree references, and fetch them into the repository.
150
151When new tree references are encountered, pull should create a corresponding
152subbranch in the top branch.
153
154Pulls will update the subtrees whose tree-references change, including creating
155trees for new sub-branches.
156
157Implementation strategies
158*************************
159
160Start from the top
161~~~~~~~~~~~~~~~~~~
162In the initial implementation, recursion into subtrees should be implemented at
163the highest level possible. This will make experimentation easier, reduce the
164chance for regressions in core code, and reduce the number of public API
165changes. This will entail some redundant post-operation determination of
166whether subtrees are present. Speed of operations involving subtrees is not a
167major concern, but operations that do not use subtrees must not be observably
168slower.
169
170Aaron Bentley believes that recursion at the top level is also easier to
171understand and debug, but Robert Collins and Vincent Ladeuil disagree.
172
173As time goes on and the design is proven, operations can be rewritten as more
174intrusive changes, in order to provide better performance or better handling of
175edge cases. It may make sense to implement them on NestedTrees, so that they
176can take advantage of its subtree caching.
177
178However, some low-level operations would be dubious to implement as recursive.
179For example, a recursive Tree.id2path might open several subtrees in order to
180determine a single path. It would be better to support a batch operation in
181NestedTrees.
182
183Fast subtree detection
184~~~~~~~~~~~~~~~~~~~~~~
185The obvious way to prevent slowness when there are no subtrees is to provide a
186fast way of determining whether there are subtrees. This could be provided by
187additional on-disk indices, or potentially by providing a flag indicating
188whether there are subtrees. Such a flag could be updated by Tree.iter_entries,
189to avoid re-running Tree.iter_entries. A parallel flag for iter_changes is
190also conceivable, but would be more complicated, since iter_changes is relative
191to another Tree. Further, during ``iter_changes`` it is possible to have
192subtrees that were not encountered because they were unchanged between the
193trees (as ``iter_changes`` does not always walk the entire tree).
194
195Composite Locking
196~~~~~~~~~~~~~~~~~
197Locking a NestedTrees should lock all subtrees, to reduce the potential for new
198failure modes. This suggests the need for an on-disk index of subtrees.
199
200CompositeTree
201~~~~~~~~~~~~~
202For some operations such as diff, status and export, knowing which directories
203are tree references is not essential. They can be satisfied by a Tree
204implementation that papers over tree-references, making the set of nested trees
205look like a single big tree with directories instead of tree-references. This
206implementation strategy has a limited scope, and probably a limited shelf life,
207but provides a fast way of getting coverage of several important commands.
208
209Scope
210*****
211Ultimately, all commands should support nested trees. Initial work is focused
212on:
213
214- checkout
215- branch
216- push
217- pull
218- merge
219- revert
220- mv
221- status
222- diff
223- commit
224- export
225
226
227Data storage
228************
229
230Trees
231~~~~~
232The root-ids of trees must be unique, so that the same file-id can be used in
233both the containing tree and the subtree, to simplify access within trees.
234Tree references are an inventory type that is distinct from a directory, and
235has a revision-id associated with it.
236All modern working trees support tree references. Indices may be provided to
237ensure fast access to the list of subtrees.
238
239Because of the need to use branches for recursion, it would be desirable to
240associate RevisionTrees with branches. The alternative is for many operations
241to accept Tree + Branch as input, and return Tree, Branch pairs.
242
243Branches
244~~~~~~~~
245A new branch format, "subbranches", is introduced which provides multiple
246sub-branches, with their data referenced by file-id. A new branch refrerence
247format, "subbranch-reference", is introduced which refers to sub-branches in a
248"subbranches" branch.
249
250Repositories
251~~~~~~~~~~~~
252Some repository formats have 'subtree' variants, e.g. pack-0.92-subtree,
253development-subtree. These are hidden, experimental formats that support
254storing tree-references in their inventory formats. The most recent format
255which supports subtrees is RepositoryFormatKnitPack3.
256
257Repository indexing might be extended to provide fast access to
258tree-references.
259
260Commands
261********
262
263The following new commands are introduced:
264
265``split`` Convert a single working tree into two trees, one inside the other.
266
267``join --nested`` Cause an inner tree to be treated as a subtree. The outer
268tree's branch must be in the new "subbranches" format. The inner tree's branch
269will be cloned into the "subbranches" branch, and the local branch will be
270replaced with a "subbranch-reference". Finally, a tree-reference will be
271added to the containing tree.
272
273API Changes
274***********
275
276Introduce NestedTrees
277~~~~~~~~~~~~~~~~~~~~~
278New class to provide services for sets of nested trees, including coordinating
279locking, caching Tree instances, and mapping file-ids and paths to the
280appropriate Tree and Branch. Includes::
281
282 NestedTrees.lock_read
283
284 NestedTrees.lock_write
285
286 NestedTrees.unlock
287
288 NestedTrees.paths_info(self, paths)
289 - return a list of tuples of Tree, relpaths, where relpaths is a list of
290 relative paths, and Tree is the subtree that contains them.
291
292 NestedTrees.get_tree_and_treepath
293 - return the tree and relative path within that tree of a file-id
294
295 NestedTrees.apply_inventory_delta
296 - splits an inventory delta into the affected subtrees and applies it to them
297 all
298
299 NestedTrees.iter_changes
300 - provide iter_changes over a set of nested subtrees. Emits tree-references
301 in preference to tree roots.
302
303
304Introduce NestedTreeTransform
305~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
306New class to permit smooth recursion of TreeTransform operations like merge and
307revert even when the subtree boundaries differ. API essentially the same as
308TreeTransform, except that tree-references can have children, as directories
309do.
310
311Introduce CompositeTree
312~~~~~~~~~~~~~~~~~~~~~~~
313New class to provide easy transition of superficial commands like diff, status,
314export. API is a subset of Tree API. Additional methods::
315
316 CompositeTree.maybe_composite
317
318 - return a CompositeTree if the input tree has subtrees, otherwise return the
319 input Tree. This restricts the scope of any regressions to Trees that
320 are actually using the features.
321
322New Tree methods
323~~~~~~~~~~~~~~~~
324
325 get_nested_tree_and_branch(file_id, branch)
326
327 - Return a Tree and Branch for the tree-reference with the specified file_id
328
329Tree changes
330~~~~~~~~~~~~
331
332 WorkingTree will cache the list of tree-references, to accelerate
333 WorkingTree.iter_references. This may be an in-memory cache, or it may
334 require a new format.
335
336 WorkingTree.pull recurses downwards by default. Subtrees are pulled from the
337 reference location of the specified branch.
338
339 MutableTree.commit recurses downwards by default.
340
341 WorkingTree.revert recurses downwards by default.
342
343 Merger recurses downwards by default. This is not equivalent to running merge
344 in each of the subtrees-- it uses the tree-reference revision-id to determine
345 which revision to merge into each subtree, recursively. Merger should not
346 care whether subtree boundaries have changed. Like WorkingTree.pull, it
347 fetches from the reference location of the branch associated with the tree.
348
349New Branch methods
350~~~~~~~~~~~~~~~~~~
351 get_subbranch
352
353 - Return branch for tree reference
354
355Branch changes
356~~~~~~~~~~~~~~
357
358 pull recurses into reference branches, and pulls *from* the source's reference
359 branches.
360
361Repository changes
362~~~~~~~~~~~~~~~~~~
363
364 fetch provides a list of tree-reference revision ids/file-id pairs for the
365 revisions that were fetched. Fetch automatically fetches all revisions
366 associted with tree-references that were fetched.
367
368Use Cases
369*********
370
371Case 1
372~~~~~~
373Barry works on a project with three libraries. He wants to keep up to date
374with the tip of those libraries, but he doesn't want them to be part of his
375source tree.
376
377Example commands::
378
379 Set up the tree:
380 $ bzr branch --nested http://library1 project
381 $ bzr branch --nested http://library2 project
382 $ bzr branch --nested http://library3 project
383 $ bzr commit project -m "Added three libraries"
384
385 Update a library to tip:
386 $ bzr pull -d project/library1 http://library1
387
388Case 2
389~~~~~~
390Now, Barry wants to add a fourth library.
391
392Example commands::
393
394 $ bzr branch --nested http://library4 project
395
396Case 3
397~~~~~~
398Barry wants to publish his project.
399
400Example commands::
401
402 $ bzr push -d project bzr+ssh://project/trunk
403
404Case 4
405~~~~~~
406Barry decides to make part of his project into another library
407
408Example commands::
409
410 $ bzr split --nested project/newlibrary
411
412Case 5
413~~~~~~
414Curtis wants to hack on Barry's project
415
416Example commands::
417
418 $ bzr branch http://project/trunk
419
420Case 6
421~~~~~~
422Barry wants to drop one of the libraries he was using
423
424Example commands::
425
426 $ rm project/library1
427 $ bzr commit project -m "Removed library1"
428
429Case 7
430~~~~~~
431Curtis has made changes to one of the libraries. Barry wants to merge Curtis'
432changes into his copy.
433
434Example commands::
435
436 $ bzr merge -d project http://curtis.org/trunk#library2
437
438 Or alternatively:
439 $ bzr merge -d project/library2 http://curtis.org/trunk#library2
440
441Case 8
442~~~~~~
443Curtis has made changes to Barry's main project. Barry wants to merge Curtis'
444changes into his copy.
445
446Example commands::
447
448 $ bzr merge -d project http://curtis.org/trunk
449
450
451Case 9
452~~~~~~
453Barry makes changes in his project and in a library, and he runs status
454
455Example commands::
456
457 $ echo bar > project/foo
458 $ echo qux > project/library2/baz
459 $ bzr status project
460 M foo
461 M library2/baz
462
463Case 10
464~~~~~~~
465Barry wants to upgrade the bazaar format of his project
466
467Example commands::
468
469 $ bzr upgrade project
470
471Case 11
472~~~~~~~
473Curtis wants to apply Barry's latest changes.
474
475Example commands::
476
477 $ bzr merge -d project http://project/trunk
478
479Case 12
480~~~~~~~
481Danilo wants to start a project with two libraries using nested trees from
482scratch.
483
484Example commands::
485
486 $ bzr init project
487 $ bzr branch --nested http://library4 project
488 $ bzr branch --nested http://library5 project
489 $ bzr commit project -m "Created new project."
490
491Case 13
492~~~~~~~
493Edwin has a project that doesn't use nested trees and he wants to start using
494nested trees.
495
496Example commands::
497 $ bzr split --nested project/subdir
498
499Case 14
500~~~~~~~
501Françis has a project with nested trees where the containing tree uses one
502Bazaar format and the subtree uses a different Bazaar format.
503
504Not supported.
505
506Case 15
507~~~~~~~
508Barry commits some changes to a library and to the main project, and then
509discovers the changes are not appropriate. He has not yet pushed his changes
510anywhere.
511
512Example commands::
513
514 $ bzr merge -d project http://library2
515 $ bzr commit project -m "Updated library2"
516 $ bzr uncommit project --force
517
518Case 16
519~~~~~~~
520Barry commits some changes to a library and to the main project, publishes his
521branch, and then discovers the changes are not appropriate.
522
523Example commands::
524
525 $ bzr merge -d project http://library2
526 $ bzr commit project -m "Updated library2"
527 $ bzr push -d project
528 $ bzr revert project
529 $ bzr commit project -m "Reverted inappropriate changes."
530 $ bzr push -d project
531
532Case 17
533~~~~~~~
534Gary is writing a project. Henninge wants to split a library out of it.
535
536Example commands::
537
538 $ bzr branch project
539 $ bzr split project/library6
540 $ mv project/library6 .
541 $ rm project
542 $ bzr commit -m "split library6 into its own library."
543
544Case 18
545~~~~~~~
546Henning wants to update to receive Gary's latest changes.
547
548Example commands::
549
550 $ bzr merge -d library6
551
552Case 19
553~~~~~~~
554Gary wants to update to receive Henninge's changes, including splitting a
555library out.
556
557Example commands::
558
559 $ bzr split --nested project/library6
560 $ bzr commit project -m "Turned library6 into a library"
561 $ bzr merge -d project/library6 http://library6
562 $ bzr commit project -m "Merge Henninge's changes."
563
564
565Case 20
566~~~~~~~
567Gary wants to update to receive Henninge's changes, without splitting a library
568out.
569
570 $ bzr split --nested project/library6
571 $ bzr commit project -m "Turned library6 into a library"
572 # i.e. a cherrypick that skips the revision where library6 became a library.
573 $ bzr merge -d project/library6 http://library6 -r 5..-1
574 $ bzr commit project -m "Merge Henninge's changes."
575
576Case 21
577~~~~~~~
578
579John works on a project called FooBar, but has decided that it would be better
580structured as two projects, where Bar is a library that may be of general use
581outside of Foo. As it happens, bar already has its own subdirectory.
582
583He runs:
584::
585
586 # Convert into two trees: foobar and foobar/bar.
587 # In each tree, files will be removed and deleted. In foobar/bar, "bar"
588 # will have been moved to become the tree root.
589 # These changes will be committed later.
590 $ bzr upgrade foobar --format=subbranches
591 $ bzr split foobar/bar
592
593 # Add a tree-reference from foobar to foobar/bar, change bar's branch
594 # to a reference to subbranch in foobar's branch.
595 $ bzr join --nested foobar/bar
596
597 # This recurses into foobar/bar and commits the deletion of the containing
598 # tree. In foobar, it commits a kind change for 'bar' from directory to
599 # tree-reference, and the deletion of the contents of bar.
600 $ bzr commit foobar
601
602This commits new revisions to foobar and bar, and foobar's tree-reference bar
603refers to the revision-id of bar.
604
605Next, he adds two new files: foobar/baz and foobar/bar/qux::
606
607 $ vi foobar/baz
608 $ vi foobar/bar/qux
609 # This adds qux to foobar/bar and adds baz to foobar.
610 $ bzr add foobar
611
612Since foobar/bar/qux is in a commitable state and foobar/baz is not, he invokes
613::
614
615 $ bzr commit foobar/bar
616
617This commits foobar/bar/baz/qux to the subtree and commits foobar/bar to the
618containing tree.
619
620(Had he wanted to commit to just the subtree, or just the containing tree, he
621could have specified an option.)
622
623
624Case 21
625~~~~~~~
626
627Robert wants to hack on a project, Baz, that is structured as a nested tree,
628which uses the library "quxlib", from quxlib.org.
629
630He runs:
631::
632
633 $ bzr branch http://baz.org/dev baz
634
635This creates a "subbranches" branch and working tree for baz, as normal. Since
636tree-references were encountered, it adds subbranches for them to the baz
637branch. All data is retrieved from baz.org, not quxlib.org.
638
639It creates a working tree for quxlib with a subbranch-reference. It uses the
640revision-id from the tree-reference in the containing tree, not the head
641revision at baz.org. This allows Robert to get a known-good nested tree.
642
643Later, Robert decides to update the version of quxlib being used to the latest
644from quxlib.org. He runs::
645
646 $ bzr pull -d http://quxlib.org
647
648This updates the version of quxlib in the working tree, which mean that baz is
649now out-of-date with its last-committed tree. Unfortunately, the new rev on
650quxlib is not completely compatible with the old one, and Robert must tweak a
651few files before Baz runs properly. Once he has done so, he runs::
652
653 $ bzr commit baz
654
655Now he has committed a known-good nested tree, and the baz working tree is once
656again up-to-date.
657
658
659User documentation
660******************
661
662For many large projects, it is often useful to incorporate libraries
663maintained elsewhere or to construct them from multiple subprojects.
664While it is easy for a single user to set up a particular layout of
665multiple branches by hand, the different branches really need to be
666linked together if others are to reproduce the desired layout, and
667if the relationships are going to be managed over time.
668
669Bazaar has good support for building and managing external libraries
670and subprojects via a feature known as *nested trees*. In particular,
671nearly all of Bazaar's commonly used commands understand nested trees
672and Do The Right Thing as explained below. The relationship is hierarchical:
673the containing tree knows about its nested trees, but nested trees are unaware
674of the tree (or trees) containing them.
675
676At the moment, *nested trees* are the only type of nested item
677supported though *nested files* may be supported in the future.
678Nested trees may contain other nested trees as required.
679
680Note: This feature requires a recent branch format such as ``2.0``
681or later.
682
683
684Nesting an external project
685---------------------------
686
687To link an external project into a branch, use the ``branch`` command
688with the ``--nested`` option like this::
689
690 bzr branch --nested SOURCE-URL TARGET-DIR
691
692For example, assuming you already have a ``src/lib`` directory where
693libraries are kept::
694
695 bzr branch --nested http://example.com/xmlsaxlib src/lib/sax
696
697This will create a nested branch in the ``src/lib/sax`` directory,
698join it into the containing branch and save the source location.
699
700If you now run ``bzr status``, it will show the nested branch as
701uncommitted changes like this::
702
703 + src/lib/sax
704 + src/lib/sax/README
705 + src/lib/sax/parser.py
706 ...
707
708To record this change, use the ``commit`` command as you normally would::
709
710 bzr commit -m "added SAX parsing library"
711
712Note that Bazaar stores the tip revision of each nested branch. This
713is an important feature in that it's then easy to reproduce the exact
714combination of libraries used for historical revisions. It also means
715that other developers pulling or merging your changes will get nested
716branches created for them at the right revisions of each.
717
718
719Refreshing a nested branch
720--------------------------
721
722As bugs are fixed and enhancements are made to nested projects, you
723will want to update the version being used. To do this, ``pull`` the
724latest version of the nested branch. For example::
725
726 bzr pull -d src/lib/sax
727
728If the latest revision is too unstable, you can always use the ``-r``
729option on the ``pull`` command to nominate a particular revision or tag.
730
731Now that you have the required version of the code, you can make
732any required adjustments (e.g. API changes), run your automated tests
733and commit something like this::
734
735 view src/lib/sax/README
736 (hack, hack, hack)
737 make test
738 bzr commit -m "upgraded SAX library to version 2.1.3"
739
740
741Changing a nested tree
742----------------------
743
744As well as keeping track of which revisions of external libraries
745are used over time, one of the reasons for nesting projects is to
746make minor changes. You may want to do this in order to fix and
747track particular bugs you need addressed. In other cases, you may want
748to make various local enhancements that aren't valuable outside
749the context of your project.
750
751As support for nested branches is integrated into most commonly
752used commands, this is actually quite easy to do: simply make
753the change to the required files as you normally would! For example::
754
755 edit src/lib/sax/parser.py
756 bzr commit -m "fix bug #42 in sax parser"
757
758Note that Bazaar is smart enough to recurse by default into nested
759branches, commit changes there, and commit the new nested branch tips
760in the current branch. Both commits get the same commit message.
761
762If you want to only commit the change to a nested branch for now, you
763can change into the nested branch before running commit like this::
764
765 cd src/lib/sax
766 bzr commit -m "fix bug #42 in sax parser"
767
768Alternatively, you can use a selective commit like this::
769
770 bzr commit -m "fix bug #42 in sax parser" src/lib/sax
771
772
773Reviewing nested tree changes
774-----------------------------
775
776Just like ``commit``, the ``status`` and ``diff`` commands implicitly
777recurse into nested trees. In the case of ``status``, it shows both the
778nested tree as having a pending change as well as the items within it that have
779changed. For example::
780
781 M src/lib/sax
782 M src/lib/sax/parser.py
783
784Once again, if you change into a nested tree though, ``status`` and
785``diff`` will operate just on that tree and not recurse upwards by
786default.
787
788
789Browsing nested tree history
790----------------------------
791
792As the branches of nested trees have their own history, the ``log`` command
793shows just the history of the containing branch. To see the history for
794a nested branch, nominate the branch explicitly like this::
795
796 bzr log src/lib/sax
797
798Note however that ``log -v`` and ``log -p`` on the containing branch
799will show what files in nested branches were changed in each revision.
800
801
802Splitting out a project
803-----------------------
804
805If you already have a large project and wish to partition it into
806reusable subprojects, use the ``split`` command. This takes an existing
807directory and makes it a separate branch. For example, imagine you have
808a directory holding UI widgets that another project would like to
809leverage. You can make it a separate branch like this::
810
811 bzr split src/uiwidgets
812
813To make the new project available to others, push it to a shared location
814like this::
815
816 cd src/uiwidgets
817 bzr push bzr://example.com/uiwidgets
818
819You also need to link it back into the original project as a nested branch
820using the ``join`` command like this (assuming the current directory is
821``src/uiwidgets``)::
822
823 bzr join --nested .
824 bzr commit -m "uiwidgets is now a nested project"
825
826Similar to ``branch --nested``, ``join --nested`` joins the nominated directory
827(which must hold a branch) into the containing tree. In order to make sure
828that all versions of a tree can be reproduced, the branches of nested trees
829share a repository with their containing tree.
830
831
832Virtual projects
833----------------
834
835By design, Bazaar is strict about tracking the actual revisions used of
836nested branches over time. Without this, projects cannot accurately
837reproduce exactly what was used to make a given build. There are
838isolated use cases though where is advantageous to say "give me the
839latest tip of these loosely coupled branches". To do this, create a
840small 'virtual project' which is just a bunch of *unpegged* nested
841branches. To mark nested branches as unpegged, use the ``--no-pegged``
842option of the ``join`` command like this::
843
844 bzr join --nested --no-pegged [DIR]
845
846To stop the nested branch tips from floating and to begin recording
847the tip revisions again, use the ``pegged`` option::
848
849 bzr join --nested --pegged [DIR]
850
851After changing whether one or more nested branches are pegged or not, you
852need to ``commit`` the branch to record that metadata. (The pegged state
853is recorded over time.)
854
855For example, you may be managing a company intranet site as a project
856which is nothing more than a list of unrelated departmental websites
857bundled together. You can set this up like this::
858
859 bzr init intranet-site
860 cd intranet-site
861 bzr branch bzr://ourserver/websites/research
862 bzr branch bzr://ourserver/websites/development
863 bzr branch bzr://ourserver/websites/support
864 bzr branch bzr://ourserver/websites/hr
865 bzr join --nested --no-pegged research
866 bzr join --nested --no-pegged development
867 bzr join --nested --no-pegged support
868 bzr join --nested --no-pegged hr
869 bzr commit -m "initial configuration of intranet-site"
870
871Publishing the overall site is then as easy as going to the server
872hosting your intranet and running something like::
873
874 bzr branch http://mymachine//projects/intranet-site
875
876Refreshing the overall site is as easy as::
877
878 bzr pull
879
880Virtual projects are also useful for providing a partial 'view' over
881a large project containing a large number of subprojects. For example,
882you may be working on an office suite and have a bunch of developers
883that only care about the word processor. You can create a virtual
884project for them like this::
885
886 bzr init wp-modules
887 cd wp-modules
888 bzr branch ../common
889 bzr branch ../printing
890 bzr branch ../spellchecker
891 bzr branch ../wordprocessor
892 bzr join --nested --no-pegged common
893 bzr join --nested --no-pegged printing
894 bzr join --nested --no-pegged spellchecker
895 bzr join --nested --no-pegged wordprocessor
896 bzr commit -m "initial configuration of wp-modules"
897
898Those developers can then get bootstrapped faster and have *just* the
899subprojects they care about by branching from ``wp-modules``.
900
901
902Nested branch tips & tricks
903---------------------------
904
905As explained above, most of Bazaar's commonly used commands recurse
906downwards into nested branches by default. To prevent this recursion,
907use the ``--no-recurse-nested`` option on various commands (including
908``commit``, ``status`` and ``diff``) that support it.
909
910Thanks to plugins like bzr-svn and bzr-git, Bazaar has strong support
911for transparently accessing branches managed by foreign VCS tools. This
912means that Bazaar can support projects where nested branches are hosted
913in supported foreign systems. For example, to nest a library maintained
914in Subversion::
915
916 bzr branch --nested svn://example.com/xmlhelpers src/lib/xmlhelpers
917
918If you want revisions to be committed both to a remote location and a
919local location, make the top-level branch a bound branch. (Nested branches
920have no configuration of their own.)
921
922Most likely, you will have some branches that are identical to their upstream
923version and can be pulled, and some that have local changes and must be merged.
924You can update all of them at once using ``merge --pull``. This will pull
925into the trees with no local changes, and merge into the ones with local
926changes. Afterward, you should commit, which will commit only into the
927trees that were merged into.
928
929As you'd expect, a nested branch can be moved or deleted using the
930normal commands. For example, after splitting out a subproject, you
931may want to change its location like this::
932
933 bzr mv src/uiwidgets src/lib/uiwidgets
934 bzr commit -m "move uiwidgets into src/lib"
935
936Things to be aware of
937---------------------
938
939Commands like ``commit`` and ``push`` need online access to the locations
940for nested branches which have updated their tip. In particular, ``commit``
941will update any changed nested branches first and only commit to the
942containing branch if all nested branch commits succeed. If you are working
943offline, you may want to ensure you have a local mirror location defined
944for nested branches you are likely to tweak. Alternatively, the
945``no-recurse-nested`` option to the ``commit`` command might to useful to
946commit some changes, leaving the nested branch commits until you are back
947online.
948
949A given top level tree cannot contain multiple copies of a nested tree.
950As a consequence, you cannot nest two projects if they both nest
951the same project somewhere within them. This limitation may be removed
952in the future. In the meantime, consider restructuring things so that each
953project is only nested once (and leverage symbolic links as appropriate).
954In most programming environments, having different parts of the project
955using different versions of a library is an integration no-no anyhow,
956so enforcing *one* common revision is the right way to prevent this from
957happening.
958
959At the moment, nested trees need to be incorporated as a whole.
960Filtered views can to used to restrict the set of files and directories
961logically seen. Currently though, filtered views are a lens onto a tree:
962they do not delete other files and the exposed files/directories must
963have the same paths as they do in the original branch. In the future,
964we may add support for nesting and moving selected files from a
965(read-only) nested branch something like this::
966
967 bzr nested DIR --file LICENSE --file doc/README::README
968 bzr commit -m "change which files are nested from project DIR"
969
970If you require this feature, please contact us with your needs.
971
972Design decisions
973****************
974
975The branches of subtrees shall share a repository with the containing tree.
976
977The branches of subtrees shall be in a special format that shares a single
978last_revision file that is stored in the containing branch.
979
980The subtree branches shall be referenced in the last_revision file by file-id.
981
982Subtree branches shall not support individual configuration.
983
984Fetch shall automatically fetch the revisions mentioned by tree-references,
985recursively.
986
987The reserved revision-id "head:" shall be used in tree-references to refer to
988the tip revision of a branch.
989
990bzr-svn repositories with externals shall behave as though the multiple
991repositories were a single Bazaar repository with multiple branches.
68992
69Shall commands recurse downwards by default?993Shall commands recurse downwards by default?
70~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~994~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -76,10 +1000,10 @@
76 - It is hard to accidentally produce inconsistent trees1000 - It is hard to accidentally produce inconsistent trees
77 - Inconsistent trees are hard for remote users to handle1001 - Inconsistent trees are hard for remote users to handle
78 - Accidentally committing too many things at once is easy to resolve1002 - Accidentally committing too many things at once is easy to resolve
1003 - It is hard to accidentally commit too many things at once
791004
80Cons:1005Cons:
811006
82 - It is hard to accidentally commit too many things at once
83 - Accidentally committing nuclear launch codes is easier to do1007 - Accidentally committing nuclear launch codes is easier to do
84 - More risk of exposing users to bugs1008 - More risk of exposing users to bugs
85 - Makes incompleteness more glaring1009 - Makes incompleteness more glaring
@@ -98,8 +1022,8 @@
981022
99 - the "name" of subbranches can change from revision to revision. In fact,1023 - the "name" of subbranches can change from revision to revision. In fact,
100 subbranches may have no name in a given revision.1024 subbranches may have no name in a given revision.
101 - a user may want to get revision X of a subbranch named "foo" in revision Y of1025 - a user may want to get revision X of a subbranch named "foo" in revision Y
102 the top branch.1026 of the top branch.
1031027
104The syntax will be ``BRANCH#SUBBRANCH``, e.g. ``lp:bigproject#subproject``.1028The syntax will be ``BRANCH#SUBBRANCH``, e.g. ``lp:bigproject#subproject``.
105``BRANCH`` is a regular URL and ``SUBBRANCH`` is a path within BRANCH's tree1029``BRANCH`` is a regular URL and ``SUBBRANCH`` is a path within BRANCH's tree
@@ -114,8 +1038,9 @@
114cross subtree boundaries, e.g. a merge in the top tree can move a file between1038cross subtree boundaries, e.g. a merge in the top tree can move a file between
115subtrees.1039subtrees.
1161040
117The downside is that we can't have cheap support for subtrees that are copies of1041The downside is that we can't have cheap support for subtrees that are copies
118one another, because we wouldn't know which copy to apply sets of changes to.1042of one another, because we wouldn't know which copy to apply sets of changes
1043to.
1191044
1201045
121Shall we use root-ids for tree references?1046Shall we use root-ids for tree references?
@@ -136,8 +1061,8 @@
136~~~~~~~~~~~~~~~~~~~~~~~~~~1061~~~~~~~~~~~~~~~~~~~~~~~~~~
1371062
138Yes. It matches existing behaviour by failing earlier, and the extra cost does1063Yes. It matches existing behaviour by failing earlier, and the extra cost does
139not seem onerous. (To be fully efficient this requires an index of the subtrees,1064not seem onerous. (To be fully efficient this requires an index of the
140otherwise we need to scan the fully inventory/dirstate.)1065subtrees, otherwise we need to scan the fully inventory/dirstate.)
1411066
142(Also, this decision can be changed later with no compatibility concerns.)1067(Also, this decision can be changed later with no compatibility concerns.)
1431068
@@ -149,17 +1074,19 @@
149local last revision's revno would change (i.e. is a non-lhs parent in the merge1074local last revision's revno would change (i.e. is a non-lhs parent in the merge
150source). This is expected to be the most common way to update nested trees.1075source). This is expected to be the most common way to update nested trees.
1511076
152The existing "bzr merge --pull" behaviour will be renamed to "bzr merge --pull-renumber".1077The existing "bzr merge --pull" behaviour will be renamed to "bzr merge
1078--pull-renumber".
1531079
154"bzr merge" (with no "--pull") will do a merge in all trees. "bzr pull" will do1080"bzr merge" (with no "--pull") will do a merge in all trees. "bzr pull" will
155a pull in all trees.1081do a pull in all trees.
1561082
157The rationale is that a very common use-case is that the top tree is a project1083The rationale is that a very common use-case is that the top tree is a project
158the user is actively committing to, and the subtrees are mainly libraries that1084the user is actively committing to, and the subtrees are mainly libraries that
159are being mirrored. So a behaviour that forced every update to be a merge would1085are being mirrored. So a behaviour that forced every update to be a merge
160be undesirable for the mirrored subtrees, but an update that is a pull wouldn't1086would be undesirable for the mirrored subtrees, but an update that is a pull
161suit the changing top tree. And the existing "merge --pull" (that can renumber1087wouldn't suit the changing top tree. And the existing "merge --pull" (that can
162revisions) isn't desireable for either the top tree or subtrees in this case.1088renumber revisions) isn't desireable for either the top tree or subtrees in
1089this case.
1631090
1641091
165What should uncommit do?1092What should uncommit do?
@@ -175,7 +1102,14 @@
175 $ bzr uncommit1102 $ bzr uncommit
1761103
177will not cause a change in subtrees, since the top-level commit did not affect1104will not cause a change in subtrees, since the top-level commit did not affect
178them.1105them. But on the other hand:
1106
1107 $ echo foo > subtree/versioned-file-in-subtree.txt
1108 $ bzr ci -m "Change file"
1109 $ bzr uncommit
1110
1111will first commit to the subtree, then to the top tree. The uncommit will
1112restore both trees to their previous state.
1791113
1801114
181Shall we use a CompositeTree object as a shim to make existing commands work?1115Shall we use a CompositeTree object as a shim to make existing commands work?
@@ -189,13 +1123,10 @@
189Some subtrees should have commits and some should not. How?1123Some subtrees should have commits and some should not. How?
190~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1124~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1911125
192We won't do this initially. Flagging some sub-trees as mirror-only or similar1126We will not provide special support for this initially. We might later support
193sounds like a nice feature, but we can add this later (and it may only require a1127flagging some sub-trees as mirror-only something similar, but this seems like
194working tree format bump to add).1128it could be a general feture not specific to nesting. (and it may only require
1951129a working tree format bump to add).
196It would be nice to have more infrastructure in general to handle mirrors, and
197this is not specific to nested trees.
198
1991130
200How do we handle files that are moved into subtrees (from another tree in the same top tree)?1131How do we handle files that are moved into subtrees (from another tree in the same top tree)?
201~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1132~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -203,128 +1134,97 @@
203Add a revision property:1134Add a revision property:
204"Files-from-other-trees: (rev-id: [f-id, ...]), ..."1135"Files-from-other-trees: (rev-id: [f-id, ...]), ..."
2051136
206(Once we can do cherry-pick merges, we might use those instead?)1137(Once we can record cherry-pick merges, we might use those instead, but it
2071138depends on their history-fetching requirements.)
2081139
2091140
210Handling svn:externals1141
211~~~~~~~~~~~~~~~~~~~~~~1142
2121143Comparison with other systems
213svn externals commonly have references to the tip of some other branch.1144*****************************
214Because we want a deterministic representation of the inventory when1145
215pulling from svn, we can't put the specific revision-id into the inventory1146Git submodules
216at that time. However, we do want to bring down all the relevant data at1147~~~~~~~~~~~~~~
217the time of fetching, so that we can later branch locally. This seems to 1148
2181149This allows separate repositories to be used for submodules. At the UI layer,
219Decided questions1150they are quite different, because submodules does not attempt to integrate
220*****************1151subtree support into the core commands.
2211152
222The branches of subtrees shall share a repository with the containing tree.1153Mercurial Forests
2231154~~~~~~~~~~~~~~~~~
224The branches of subtrees shall be in a special format that shares a single1155
225last_revision file that is stored in the containing branch.1156The wiki page does not give confidence that this is a well-maintained project.
2261157It seems similar to config-manager-- its 'snapshot' files are like
227The subtree branches shall be referenced in the last_revision file by file-id.1158config-manager's config files, describing what branches to get and where to put
2281159them, optionally specifying a revision. No metadata about nesting is stored in
229Subtree branches shall not support individual configuration.1160the tree. Optionally, a 'snapshot.txt' file may be stored in the containing
2301161tree, but it can also be stored somewhere else.
231Fetch shall automatically fetch the revisions mentioned by tree-references,1162
232recursively.1163There is no attempt to integrate subtree support into the core commands.
2331164
234The reserved revision-id "head:" shall be used in tree-references to refer to1165Mercurial Nested Repositories
235the tip revision of a branch.1166~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2361167This design was for an integrated feature, but there are apparently 4
237bzr-svn repositories with externals shall behave as though the multiple1168implementations as extensions. While it does integrate subtree support into
238repositories were a single Bazaar repository with multiple branches.1169core commands, this may be off by default: "The alternative that I lean towards
2391170is to not recurse unless explicitly instructed to. Most probably, only a few
2401171commands should arguably even be aware of modules."
241Use Cases1172
242*********1173Command comparison:
2431174
244Case 11175- hg module add ~= bzr join --nested
245~~~~~~1176- hg module remove ~= bzr remove --keep
246Barry works on a project with three libraries. He wants to keep up to date1177- hg module record's functionality is part of nested commits in nested trees.
247with the tip of those libraries, but he doesn't want them to be part of his1178
248source tree.1179Like submodules, this stores location information in versioned data: a
2491180.hgmodules directory.
250Case 21181Like submodules and nested trees, particular revisions are recorded.
251~~~~~~1182
252Now, Barry wants to add a fourth library.1183Subversion "svn:externals"
2531184~~~~~~~~~~~~~~~~~~~~~~~~~~
254Case 31185Like bzr, uses per-file metadata. Like submodules and nested repositories,
255~~~~~~1186locations are versioned data. Like Forests, revisions are optional. Like
256Barry wants to publish his project.1187nested repositories, there is limited integration into core commands; checkout
2571188and update support externals, and commit may support them in the future.
258Case 41189However, there is no UI specific to creating and updating svn:externals
259~~~~~~1190references.
260Barry decides to make part of his project into another library1191
2611192Unlike all other alternatives, supports partial checkouts. This is because svn
262Case 51193natively supports partial checkouts. Also, supports checkouts of tags, because
263~~~~~~1194tags are merely a convention in svn.
264Curtis wants to hack on Barry's project1195
2651196Supports pulling in "head" subtrees too, not just specific ("known-good")
266Case 61197revisions. Nested trees supports this in order to provide high-fidelity
267~~~~~~1198imports.
268Barry wants to drop one of the libraries he was using1199
2691200Some support for single-file svn:externals (see
270Case 71201http://subversion.tigris.org/svn_1.6_releasenotes.html#externals), whereas bzr
271~~~~~~1202subtrees must be directories.
272Curtis has made changes to one of the libraries. Barry wants to merge Curtis'1203
273changes into his copy.1204Has a --ignore-externals option for checking out without pulling in the
2741205svn:externals items (svn checkout is more or less equivalent to bzr branch).
275Case 81206You can also use that option on update (more or less like bzr merge).
276~~~~~~1207
277Curtis has made changes to Barry's main project. Barry wants to merge Curtis'1208
278changes into his copy.1209Comments on differences
2791210~~~~~~~~~~~~~~~~~~~~~~~
280Case 91211externals support partial checkouts. Nested trees could gain support for this
281~~~~~~1212once Bazaar itself supports partial checkouts. Supporting a single file as a
282Barry makes changes in his project and in a library, and he runs status1213"subtree" would also depend on native bzr support. On platforms that support
2831214symlinks, using symlinks to portions of a subtree can be an effective
284Case 101215substitute.
285~~~~~~~1216
286Barry wants to upgrade the bazaar format of his project1217
2871218Future work
288Case 111219***********
289~~~~~~~1220It would be nice to support multiple copies of subtree in a master tree.
290Curtis wants to apply Barry's latest changes.1221Currently, this would lead to having multiple copies of a given file-id in the
2911222(composite) tree, which is forbidden. Allowing this would involve one of:
292Case 121223
293~~~~~~~1224- permitting multiple copies of a file-id within a tree
294Danilo wants to start a project with two libraries using nested trees from1225- not treating nested trees as composite trees
295scratch.1226- using fake file-ids within the composite tree
2961227- replacing the file-id concept with something else (e.g. path tokens)
297Case 131228
298~~~~~~~
299Edwin has a project that doesn't use nested trees and he wants to start using
300nested trees.
301
302Case 14
303~~~~~~~
304Françis has a project with nested trees where the containing tree uses one
305Bazaar format and the subtree uses a different Bazaar format.
306
307Case 15
308~~~~~~~
309Barry commits some changes to a library and to the main project, and then
310discovers the changes are not appropriate.
311
312Case 16
313~~~~~~~
314Gary is writing a project. Henninge wants to split a library out of it.
315
316Case 17
317~~~~~~~
318Henning wants to update to receive Gary's latest changes.
319
320Case 18
321~~~~~~~
322Gary wants to update to receive Henninge's changes, including splitting a
323library out.
324
325Case 19
326~~~~~~~
327Gary wants to update to receive Henninge's changes, without splitting a library
328out.
3291229
330.. vim: ft=rst1230.. vim: ft=rst

Subscribers

People subscribed via source and target branches

to all changes: