5
:status: 2012-03-17: Draft spec
14
- Never store a location in versioned data.
16
- Implementation of nested trees shall not make operations observably slower
17
for those not using nested trees.
19
- A repository that holds a revision R should be able to reconstruct the
20
whole contents of that revision, including any nested trees. Corolary:
21
if I fetch that revision, even into a branch that has no working tree, it
22
should bring across any referenced revisions, or (implicitly) add fallback
25
- The introduction or possible support for nested trees should not
26
have an impact on performance.
31
**Subtree** A tree which is inside another tree, which bzr has been asked to
32
treat as part of the outer tree.
34
**Subbranch** The branch associated with a subtree.
36
**Containing tree** A tree which has another tree inside it
38
**Tree reference** A directory in a containing tree which contains a subtree.
43
(see "Design decisions" for extended rationale)
44
By default, APIs and commands for containing trees should behave as though the
45
subtrees were plain directories. By default, commands in subtrees should not
46
affect the containing trees.
50
One of the objectives of nested trees is to provide ways of reproducing
51
historical combinations of different codebases. The dependency chain points
52
downwards, such that trees are affected by the revision of their subtrees, but
53
subtrees are oblivious to their containing trees. Just as bazaar doesn't
54
entice people to commit inconsistent trees, it should not entice people to
55
commit inconsistent combinations of containing tree and subtree. Therefore,
56
commit should recurse downwards by default.
58
Status and diff should reflect what will happen when commit is used, so they
59
should also recurse downward by default. Add almost does this already. With
60
status, diff, commit and add recursing downwards, it would be confusing to
61
users if other operations did not. Therefore, all operations should recurse
64
No upwards recursion by default
65
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
66
One of the reasons for using nested trees is to gain performance by only
67
committing in a subtree. Therefore, operations should not recurse upwards by
68
default. However, some users do want to have upwards recursion, so it should
69
be provided as an option.
71
Modelling nested trees as a composite tree
72
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
73
The idea that a set of nested trees behaves like a single, larger tree seems
74
relatively easy to grasp. Both for users and for developers, it provides a
75
clear expectation for the behaviour of nested trees. There are no obvious
76
drawbacks in terms of code clarity or performance. Therefore, it seems like a
77
good model to start with.
79
Using root file-ids for tree-references
80
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
81
The idea that tree-reference file-ids are the same as the file-ids of the
82
corresponding root directories has a nice symmetry. It is one way of ensuring
83
that "bzr split" is deterministic, and "bzr join" is deterministic. When
84
performing operations involving a tree and a split version of that tree, using
85
the same file-id makes it easy to ensure that operations such as moves and
86
renames are applied appropriately to the tree-reference. Providing mechanisms
87
whereby a tree-reference can be treated as it would if it had its old file-id
88
encroaches on the territory of path tokens or file-id aliases. Having "split"
89
cause file-id changes means that in comparing these revisions, it would be seen
90
as a deleting a directory and creating a new tree-reference with the same name.
91
Handling this correctly in operations such as merge and revert would be more
92
complicated than if it were treated as a kind change, especially when
93
unversioned files are present in the subtree.
97
The branches associated with subtrees shall be called "subbranches".
99
The branch for the top tree will be in a special format, whose last_revision
100
file lists all the last_revision info for all of the branches associated with
101
the nested tree. The .bzr directories of subtrees will have a "branch" that
102
simply indicates that the top tree's branch should be used.
104
In the top tree's last_revision file, the revision id and revno will be
105
provided, indexed by the tree-reference file-id.
107
The repository used by the top-tree's branch must be a shared repository, and
108
will be used by the sub-branches.
110
Only the top branch will have a branch.conf. When an operation on a subbranch
111
would normally use values from branch.conf it will look them up in the top
112
branch's branch.conf and adjust for the sub-location if appropriate. e.g. "bzr
113
push" in a subtree will push just that subbranch to the corresponding subbranch
114
in the configured push location of the top branch.
118
If the branches were not local, the local subtrees might not be committable,
119
and commits to the remote branch would make the local subtree out of date.
120
They should not be in a separate location from the containing branch, because
121
they might share history with the tree-reference's branch. However, those
122
local branches should not be at the same location as their tree, because the
123
tree might be deleted or moved. Indeed, they should not be anywhere within a
126
subtree branches should not be above or beside their containing branch, because
127
it could cause terrible confusion if subtrees from two different trees were
128
updating the same branches with every push, pull, commit and uncommit.
130
Subtree branches could be plain branches stored somewhere in the top tree's
131
branch, but then a lookup mechanism would be needed to translate from file_id
132
to location, and performance with large numbers of subbranches would be poor.
134
Pull and non-initial push
135
~~~~~~~~~~~~~~~~~~~~~~~~~
136
When a pull involves updates to tree references, pull will always pull into the
137
reference branch. For all new revisions in the upper branch, it will determine
138
the revision values of tree references, and fetch them into the repository.
140
When new tree references are encountered, pull should create a corresponding
141
subbranch in the top branch.
143
Pulls will update the subtrees whose tree-references change, including creating
144
trees for new sub-branches.
146
Implementation strategies
147
*************************
154
The root-ids of trees must be unique, so that the same file-id can be used in
155
both the containing tree and the subtree, to simplify access within trees.
156
Tree references are an inventory type that is distinct from a directory, and
157
has a revision-id associated with it.
158
All modern working trees support tree references. Indices may be provided to
159
ensure fast access to the list of subtrees.
161
The various methods on ``Tree`` need to be updated to handle nested trees.
163
Tree file ids are tuples containing inventory file ids, describing a path
164
to the file. This means that if a file is in a nested tree with the root
165
fileid ``file_id_a`` and the file itself has the inventory file id ``file_id_b``
166
then the tree file id is (file_id_a, file_id_b). This makes it easy to look up file ids
167
without having to load and scan all nested trees for ``file_id_b``.
171
A new branch format, "subbranches", is introduced which provides multiple
172
sub-branches, with their data referenced by file-id. A new branch refrerence
173
format, "subbranch-reference", is introduced which refers to sub-branches in a
174
"subbranches" branch.
178
Some repository formats have 'subtree' variants, e.g. pack-0.92-subtree,
179
development-subtree. These are hidden, experimental formats that support
180
storing tree-references in their inventory formats.
182
Repository indexing might be extended to provide fast access to
188
The following new options are introduced:
190
``join --reference`` Cause an inner tree to be treated as a subtree. The outer
191
tree's branch must be in the new "subbranches" format. The inner tree's branch
192
will be cloned into the "subbranches" branch, and the local branch will be
193
replaced with a "subbranch-reference". Finally, a tree-reference will be
194
added to the containing tree.
196
(this is already implemented)
201
Tree file ids as tuples
202
~~~~~~~~~~~~~~~~~~~~~~~
204
Implementation Changes
205
**********************
210
pull recurses into reference branches, and pulls *from* the source's reference
216
fetch provides a list of tree-reference revision ids/file-id pairs for the
217
revisions that were fetched. Fetch automatically fetches all revisions
218
associted with tree-references that were fetched.
225
Barry works on a project with three libraries. He wants to keep up to date
226
with the tip of those libraries, but he doesn't want them to be part of his
232
$ bzr branch --nested http://library1 project
233
$ bzr branch --nested http://library2 project
234
$ bzr branch --nested http://library3 project
235
$ bzr commit project -m "Added three libraries"
237
Update a library to tip:
238
$ bzr pull -d project/library1 http://library1
242
Now, Barry wants to add a fourth library.
246
$ bzr branch --nested http://library4 project
250
Barry wants to publish his project.
254
$ bzr push -d project bzr+ssh://project/trunk
258
Barry decides to make part of his project into another library
262
$ bzr split --nested project/newlibrary
266
Curtis wants to hack on Barry's project
270
$ bzr branch http://project/trunk
274
Barry wants to drop one of the libraries he was using
278
$ rm project/library1
279
$ bzr commit project -m "Removed library1"
283
Curtis has made changes to one of the libraries. Barry wants to merge Curtis'
284
changes into his copy.
288
$ bzr merge -d project http://curtis.org/trunk/library2
291
$ bzr merge -d project/library2 http://curtis.org/trunk/library2
295
Curtis has made changes to Barry's main project. Barry wants to merge Curtis'
296
changes into his copy.
300
$ bzr merge -d project http://curtis.org/trunk
305
Barry makes changes in his project and in a library, and he runs status
309
$ echo bar > project/foo
310
$ echo qux > project/library2/baz
317
Barry wants to upgrade the bazaar format of his project
321
$ bzr upgrade project
325
Curtis wants to apply Barry's latest changes.
329
$ bzr merge -d project http://project/trunk
333
Danilo wants to start a project with two libraries using nested trees from
339
$ bzr branch --nested http://library4 project
340
$ bzr branch --nested http://library5 project
341
$ bzr commit project -m "Created new project."
345
Edwin has a project that doesn't use nested trees and he wants to start using
349
$ bzr split --nested project/subdir
353
Françis has a project with nested trees where the containing tree uses one
354
Bazaar format and the subtree uses a different Bazaar format.
360
Barry commits some changes to a library and to the main project, and then
361
discovers the changes are not appropriate. He has not yet pushed his changes
366
$ bzr merge -d project http://library2
367
$ bzr commit project -m "Updated library2"
368
$ bzr uncommit project --force
372
Barry commits some changes to a library and to the main project, publishes his
373
branch, and then discovers the changes are not appropriate.
377
$ bzr merge -d project http://library2
378
$ bzr commit project -m "Updated library2"
379
$ bzr push -d project
380
$ bzr revert -r-2 project
381
$ bzr commit project -m "Reverted inappropriate changes."
382
$ bzr push -d project
386
Gary is writing a project. Henninge wants to split a library out of it.
391
$ bzr split project/library6
392
$ mv project/library6 .
394
$ bzr commit -m "split library6 into its own library."
398
Henning wants to update to receive Gary's latest changes.
402
$ bzr merge -d library6
406
Gary wants to update to receive Henninge's changes, including splitting a
411
$ bzr split --nested project/library6
412
$ bzr commit project -m "Turned library6 into a library"
413
$ bzr merge -d project/library6 http://library6
414
$ bzr commit project -m "Merge Henninge's changes."
419
Gary wants to update to receive Henninge's changes, without splitting a library
422
$ bzr split --nested project/library6
423
$ bzr commit project -m "Turned library6 into a library"
424
# i.e. a cherrypick that skips the revision where library6 became a library.
425
$ bzr merge -d project/library6 http://library6 -r 5..-1
426
$ bzr commit project -m "Merge Henninge's changes."
431
John works on a project called FooBar, but has decided that it would be better
432
structured as two projects, where Bar is a library that may be of general use
433
outside of Foo. As it happens, bar already has its own subdirectory.
438
# Convert into two trees: foobar and foobar/bar.
439
# In each tree, files will be removed and deleted. In foobar/bar, "bar"
440
# will have been moved to become the tree root.
441
# These changes will be committed later.
442
$ bzr upgrade foobar --format=subbranches
443
$ bzr split foobar/bar
445
# Add a tree-reference from foobar to foobar/bar, change bar's branch
446
# to a reference to subbranch in foobar's branch.
447
$ bzr join --nested foobar/bar
449
# This recurses into foobar/bar and commits the deletion of the containing
450
# tree. In foobar, it commits a kind change for 'bar' from directory to
451
# tree-reference, and the deletion of the contents of bar.
454
This commits new revisions to foobar and bar, and foobar's tree-reference bar
455
refers to the revision-id of bar.
457
Next, he adds two new files: foobar/baz and foobar/bar/qux::
461
# This adds qux to foobar/bar and adds baz to foobar.
464
Since foobar/bar/qux is in a commitable state and foobar/baz is not, he invokes
467
$ bzr commit foobar/bar
469
This commits foobar/bar/baz/qux to the subtree and commits foobar/bar to the
472
(Had he wanted to commit to just the subtree, or just the containing tree, he
473
could have specified an option.)
479
Robert wants to hack on a project, Baz, that is structured as a nested tree,
480
which uses the library "quxlib", from quxlib.org.
485
$ bzr branch http://baz.org/dev baz
487
This creates a "subbranches" branch and working tree for baz, as normal. Since
488
tree-references were encountered, it adds subbranches for them to the baz
489
branch. All data is retrieved from baz.org, not quxlib.org.
491
It creates a working tree for quxlib with a subbranch-reference. It uses the
492
revision-id from the tree-reference in the containing tree, not the head
493
revision at baz.org. This allows Robert to get a known-good nested tree.
495
Later, Robert decides to update the version of quxlib being used to the latest
496
from quxlib.org. He runs::
498
$ bzr pull -d http://quxlib.org
500
This updates the version of quxlib in the working tree, which mean that baz is
501
now out-of-date with its last-committed tree. Unfortunately, the new rev on
502
quxlib is not completely compatible with the old one, and Robert must tweak a
503
few files before Baz runs properly. Once he has done so, he runs::
507
Now he has committed a known-good nested tree, and the baz working tree is once
514
For many large projects, it is often useful to incorporate libraries
515
maintained elsewhere or to construct them from multiple subprojects.
516
While it is easy for a single user to set up a particular layout of
517
multiple branches by hand, the different branches really need to be
518
linked together if others are to reproduce the desired layout, and
519
if the relationships are going to be managed over time.
521
Bazaar has good support for building and managing external libraries
522
and subprojects via a feature known as *nested trees*. In particular,
523
nearly all of Bazaar's commonly used commands understand nested trees
524
and Do The Right Thing as explained below. The relationship is hierarchical:
525
the containing tree knows about its nested trees, but nested trees are unaware
526
of the tree (or trees) containing them.
528
At the moment, *nested trees* are the only type of nested item
529
supported though *nested files* may be supported in the future.
530
Nested trees may contain other nested trees as required.
532
Note: This feature requires a recent branch format such as ``2.0``
536
Nesting an external project
537
~~~~~~~~~~~~~~~~~~~~~~~~~~~
539
To link an external project into a branch, use the ``branch`` command
540
with the ``--nested`` option like this::
542
bzr branch --nested SOURCE-URL TARGET-DIR
544
For example, assuming you already have a ``src/lib`` directory where
547
bzr branch --nested http://example.com/xmlsaxlib src/lib/sax
549
This will create a nested branch in the ``src/lib/sax`` directory,
550
join it into the containing branch and save the source location.
552
If you now run ``bzr status``, it will show the nested branch as
553
uncommitted changes like this::
557
+ src/lib/sax/parser.py
560
To record this change, use the ``commit`` command as you normally would::
562
bzr commit -m "added SAX parsing library"
564
Note that Bazaar stores the tip revision of each nested branch. This
565
is an important feature in that it's then easy to reproduce the exact
566
combination of libraries used for historical revisions. It also means
567
that other developers pulling or merging your changes will get nested
568
branches created for them at the right revisions of each.
571
Refreshing a nested branch
572
~~~~~~~~~~~~~~~~~~~~~~~~~~
574
As bugs are fixed and enhancements are made to nested projects, you
575
will want to update the version being used. To do this, ``pull`` the
576
latest version of the nested branch. For example::
578
bzr pull -d src/lib/sax
580
If the latest revision is too unstable, you can always use the ``-r``
581
option on the ``pull`` command to nominate a particular revision or tag.
583
Now that you have the required version of the code, you can make
584
any required adjustments (e.g. API changes), run your automated tests
585
and commit something like this::
587
view src/lib/sax/README
590
bzr commit -m "upgraded SAX library to version 2.1.3"
593
Changing a nested tree
594
~~~~~~~~~~~~~~~~~~~~~~
596
As well as keeping track of which revisions of external libraries
597
are used over time, one of the reasons for nesting projects is to
598
make minor changes. You may want to do this in order to fix and
599
track particular bugs you need addressed. In other cases, you may want
600
to make various local enhancements that aren't valuable outside
601
the context of your project.
603
As support for nested branches is integrated into most commonly
604
used commands, this is actually quite easy to do: simply make
605
the change to the required files as you normally would! For example::
607
edit src/lib/sax/parser.py
608
bzr commit -m "fix bug #42 in sax parser"
610
Note that Bazaar is smart enough to recurse by default into nested
611
branches, commit changes there, and commit the new nested branch tips
612
in the current branch. Both commits get the same commit message.
614
If you want to only commit the change to a nested branch for now, you
615
can change into the nested branch before running commit like this::
618
bzr commit -m "fix bug #42 in sax parser"
620
Alternatively, you can use a selective commit like this::
622
bzr commit -m "fix bug #42 in sax parser" src/lib/sax
625
Reviewing nested tree changes
626
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
628
Just like ``commit``, the ``status`` and ``diff`` commands implicitly
629
recurse into nested trees. In the case of ``status``, it shows both the
630
nested tree as having a pending change as well as the items within it that have
631
changed. For example::
634
M src/lib/sax/parser.py
636
Once again, if you change into a nested tree though, ``status`` and
637
``diff`` will operate just on that tree and not recurse upwards by
641
Browsing nested tree history
642
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
644
As the branches of nested trees have their own history, the ``log`` command
645
shows just the history of the containing branch. To see the history for
646
a nested branch, nominate the branch explicitly like this::
650
Note however that ``log -v`` and ``log -p`` on the containing branch
651
will show what files in nested branches were changed in each revision.
654
Splitting out a project
655
~~~~~~~~~~~~~~~~~~~~~~~
657
If you already have a large project and wish to partition it into
658
reusable subprojects, use the ``split`` command. This takes an existing
659
directory and makes it a separate branch. For example, imagine you have
660
a directory holding UI widgets that another project would like to
661
leverage. You can make it a separate branch like this::
663
bzr split src/uiwidgets
665
To make the new project available to others, push it to a shared location
669
bzr push bzr://example.com/uiwidgets
671
You also need to link it back into the original project as a nested branch
672
using the ``join`` command like this (assuming the current directory is
676
bzr commit -m "uiwidgets is now a nested project"
678
Similar to ``branch --nested``, ``join --nested`` joins the nominated directory
679
(which must hold a branch) into the containing tree. In order to make sure
680
that all versions of a tree can be reproduced, the branches of nested trees
681
share a repository with their containing tree.
687
By design, Bazaar is strict about tracking the actual revisions used of
688
nested branches over time. Without this, projects cannot accurately
689
reproduce exactly what was used to make a given build. There are
690
isolated use cases though where is advantageous to say "give me the
691
latest tip of these loosely coupled branches". To do this, create a
692
small 'virtual project' which is just a bunch of *unpegged* nested
693
branches. To mark nested branches as unpegged, use the ``--no-pegged``
694
option of the ``join`` command like this::
696
bzr join --nested --no-pegged [DIR]
698
To stop the nested branch tips from floating and to begin recording
699
the tip revisions again, use the ``pegged`` option::
701
bzr join --nested --pegged [DIR]
703
After changing whether one or more nested branches are pegged or not, you
704
need to ``commit`` the branch to record that metadata. (The pegged state
705
is recorded over time.)
707
For example, you may be managing a company intranet site as a project
708
which is nothing more than a list of unrelated departmental websites
709
bundled together. You can set this up like this::
711
bzr init intranet-site
713
bzr branch bzr://ourserver/websites/research
714
bzr branch bzr://ourserver/websites/development
715
bzr branch bzr://ourserver/websites/support
716
bzr branch bzr://ourserver/websites/hr
717
bzr join --nested --no-pegged research
718
bzr join --nested --no-pegged development
719
bzr join --nested --no-pegged support
720
bzr join --nested --no-pegged hr
721
bzr commit -m "initial configuration of intranet-site"
723
Publishing the overall site is then as easy as going to the server
724
hosting your intranet and running something like::
726
bzr branch http://mymachine//projects/intranet-site
728
Refreshing the overall site is as easy as::
732
Virtual projects are also useful for providing a partial 'view' over
733
a large project containing a large number of subprojects. For example,
734
you may be working on an office suite and have a bunch of developers
735
that only care about the word processor. You can create a virtual
736
project for them like this::
741
bzr branch ../printing
742
bzr branch ../spellchecker
743
bzr branch ../wordprocessor
744
bzr join --nested --no-pegged common
745
bzr join --nested --no-pegged printing
746
bzr join --nested --no-pegged spellchecker
747
bzr join --nested --no-pegged wordprocessor
748
bzr commit -m "initial configuration of wp-modules"
750
Those developers can then get bootstrapped faster and have *just* the
751
subprojects they care about by branching from ``wp-modules``.
754
Nested branch tips & tricks
755
~~~~~~~~~~~~~~~~~~~~~~~~~~~
757
As explained above, most of Bazaar's commonly used commands recurse
758
downwards into nested branches by default. To prevent this recursion,
759
use the ``--no-recurse-nested`` option on various commands (including
760
``commit``, ``status`` and ``diff``) that support it.
762
Thanks to plugins like bzr-svn and bzr-git, Bazaar has strong support
763
for transparently accessing branches managed by foreign VCS tools. This
764
means that Bazaar can support projects where nested branches are hosted
765
in supported foreign systems. For example, to nest a library maintained
768
bzr branch --nested svn://example.com/xmlhelpers src/lib/xmlhelpers
770
If you want revisions to be committed both to a remote location and a
771
local location, make the top-level branch a bound branch. (Nested branches
772
have no configuration of their own.)
774
Most likely, you will have some branches that are identical to their upstream
775
version and can be pulled, and some that have local changes and must be merged.
776
You can update all of them at once using ``merge --pull``. This will pull
777
into the trees with no local changes, and merge into the ones with local
778
changes. Afterward, you should commit, which will commit only into the
779
trees that were merged into.
781
As you'd expect, a nested branch can be moved or deleted using the
782
normal commands. For example, after splitting out a subproject, you
783
may want to change its location like this::
785
bzr mv src/uiwidgets src/lib/uiwidgets
786
bzr commit -m "move uiwidgets into src/lib"
788
Things to be aware of
789
~~~~~~~~~~~~~~~~~~~~~
791
Commands like ``commit`` and ``push`` need online access to the locations
792
for nested branches which have updated their tip. In particular, ``commit``
793
will update any changed nested branches first and only commit to the
794
containing branch if all nested branch commits succeed. If you are working
795
offline, you may want to ensure you have a local mirror location defined
796
for nested branches you are likely to tweak. Alternatively, the
797
``no-recurse-nested`` option to the ``commit`` command might to useful to
798
commit some changes, leaving the nested branch commits until you are back
801
At the moment, nested trees need to be incorporated as a whole.
802
Filtered views can be used to restrict the set of files and directories
803
logically seen. Currently though, filtered views are a lens onto a tree:
804
they do not delete other files and the exposed files/directories must
805
have the same paths as they do in the original branch. In the future,
806
we may add support for nesting and moving selected files from a
807
(read-only) nested branch something like this::
809
bzr nested DIR --file LICENSE --file doc/README::README
810
bzr commit -m "change which files are nested from project DIR"
812
If you require this feature, please contact us with your needs.
817
The branches of subtrees shall either share a repository with the containing tree,
818
or the containing tree's repository will be (implicitly) added as a fallback
821
The branches of subtrees shall be in a special format that shares a single
822
last_revision file that is stored in the containing branch.
824
The subtree branches shall be referenced in the last_revision file by file-id.
826
Subtree branches shall not support individual configuration.
828
Fetch shall automatically fetch the revisions mentioned by tree-references,
831
The reserved revision-id "head:" shall be used in tree-references to refer to
832
the tip revision of a branch.
834
bzr-svn repositories with externals shall behave as though the multiple
835
repositories were a single Bazaar repository with multiple branches.
837
Shall commands recurse downwards by default?
838
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
844
- It is hard to accidentally produce inconsistent trees
845
- Inconsistent trees are hard for remote users to handle
846
- Accidentally committing too many things at once is easy to resolve
847
- It is hard to accidentally commit too many things at once
851
- Accidentally committing nuclear launch codes is easier to do
852
- A commit message that makes sense for the top may not make sense lower down.
855
Shall commands recurse upwards by default?
856
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
861
Shall subtree branches be addressable?
862
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
864
Ideally, yes. We might want to use the path segment parameters syntax here too.
867
Shall we model nested trees as a composite tree?
868
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
870
Yes. Users will see recurse-downwards behaviour that allows operations that
871
cross subtree boundaries, e.g. a merge in the top tree can move a file between
874
The downside is that we can't have cheap support for subtrees that are copies
875
of one another, because we wouldn't know which copy to apply sets of changes
879
Shall we use root-ids for tree references?
880
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
882
Yes. This fits well with our current lack of support of file copies. If we do
883
support file copies in future it will be possible to change this in a future
884
format, and perform deterministic upgrades to that format.
890
We should lock recursively. It matches existing behaviour by failing earlier,
891
and the extra cost does not seem onerous. (To be fully efficient this requires
892
an index of the subtrees, otherwise we need to scan the fully
895
(Also, this decision can be changed later with no compatibility concerns.)
898
How do we handle merge when the subtree hasn't diverged?
899
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
901
"bzr merge --pull" will be changed so that it will merge (not pull) when the
902
local last revision's revno would change (i.e. is a non-lhs parent in the merge
903
source). This is expected to be the most common way to update nested trees.
905
The existing "bzr merge --pull" behaviour will be renamed to "bzr merge
908
"bzr merge" (with no "--pull") will do a merge in all trees. "bzr pull" will
909
do a pull in all trees.
911
The rationale is that a very common use-case is that the top tree is a project
912
the user is actively committing to, and the subtrees are mainly libraries that
913
are being mirrored. So a behaviour that forced every update to be a merge
914
would be undesirable for the mirrored subtrees, but an update that is a pull
915
wouldn't suit the changing top tree. And the existing "merge --pull" (that can
916
renumber revisions) isn't desireable for either the top tree or subtrees in
920
What should uncommit do?
921
~~~~~~~~~~~~~~~~~~~~~~~~
923
It will recurse, and subtrees will be uncommitted back to the revision recorded
924
by the revision the top tree is uncommitting to.
926
This means that operations like::
928
$ echo foo > versioned-file-in-top-tree.txt
929
$ bzr ci -m "Change file"
932
will not cause a change in subtrees, since the top-level commit did not affect
933
them. But on the other hand:
935
$ echo foo > subtree/versioned-file-in-subtree.txt
936
$ bzr ci -m "Change file"
939
will first uncommit to the subtree, then to the top tree. The uncommit will
940
restore both trees to their previous state.
943
Some subtrees should have commits and some should not. How?
944
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
946
We will not provide special support for this initially. We might later support
947
flagging some sub-trees as mirror-only or something similar, but this seems like
948
it could be a general feature not specific to nesting. (and it may only require
949
a working tree format bump to add).
951
Comparison with other systems
952
*****************************
957
This allows separate repositories to be used for submodules.
962
The wiki page does not give confidence that this is a well-maintained project.
963
It seems similar to config-manager-- its 'snapshot' files are like
964
config-manager's config files, describing what branches to get and where to put
965
them, optionally specifying a revision. No metadata about nesting is stored in
966
the tree. Optionally, a 'snapshot.txt' file may be stored in the containing
967
tree, but it can also be stored somewhere else.
969
There is no attempt to integrate subtree support into the core commands.
971
Mercurial Nested Repositories
972
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
973
This design was for an integrated feature, but there are apparently 4
974
implementations as extensions. While it does integrate subtree support into
975
core commands, this may be off by default: "The alternative that I lean towards
976
is to not recurse unless explicitly instructed to. Most probably, only a few
977
commands should arguably even be aware of modules."
981
- hg module add ~= bzr join --nested
982
- hg module remove ~= bzr remove --keep
983
- hg module record's functionality is part of nested commits in nested trees.
985
Like submodules, this stores location information in versioned data: a
986
.hgmodules directory.
987
Like submodules and nested trees, particular revisions are recorded.
989
Subversion "svn:externals"
990
~~~~~~~~~~~~~~~~~~~~~~~~~~
991
Like bzr, uses per-file metadata. Like submodules and nested repositories,
992
locations are versioned data. Like Forests, revisions are optional. Like
993
nested repositories, there is limited integration into core commands; checkout
994
and update support externals, and commit may support them in the future.
995
However, there is no UI specific to creating and updating svn:externals
998
Unlike all other alternatives, supports partial checkouts. This is because svn
999
natively supports partial checkouts. Also, supports checkouts of tags, because
1000
tags are merely a convention in svn.
1002
Supports pulling in "head" subtrees too, not just specific ("known-good")
1003
revisions. Nested trees supports this in order to provide high-fidelity
1006
Some support for single-file svn:externals (see
1007
http://subversion.tigris.org/svn_1.6_releasenotes.html#externals), whereas bzr
1008
subtrees must be directories.
1010
Has a --ignore-externals option for checking out without pulling in the
1011
svn:externals items (svn checkout is more or less equivalent to bzr branch).
1012
You can also use that option on update (more or less like bzr merge).
1015
Comments on differences
1016
~~~~~~~~~~~~~~~~~~~~~~~
1017
externals support partial checkouts. Nested trees could gain support for this
1018
once Bazaar itself supports partial checkouts. Supporting a single file as a
1019
"subtree" would also depend on native bzr support. On platforms that support
1020
symlinks, using symlinks to portions of a subtree can be an effective