~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to doc/shared_repository_layouts.txt

  • Committer: Robert Collins
  • Date: 2007-05-07 16:48:14 UTC
  • mto: This revision was merged to the branch mainline in revision 2485.
  • Revision ID: robertc@robertcollins.net-20070507164814-wpagonutf4b5cf8s
Move HACKING to docs/developers/HACKING and adjust Makefile to accomodate this.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
=======================
 
2
SharedRepositoryLayouts
 
3
=======================
 
4
 
 
5
.. sectnum::
 
6
 
 
7
Bazaar is designed to give you flexibility in how you layout branches inside a shared repository. 
 
8
This flexibility allows users to tailor Bazaar to their workflow,
 
9
but it also leads to questions about what is a "good" layout.
 
10
We present some alternatives and give some discussion about the benefits of each.
 
11
 
 
12
One key point which should be mentioned is that any good layout should somehow highlight
 
13
what branch a "general" user should grab. In SVN this is deemed the "``trunk/``" branch,
 
14
and in most of the layouts this naming convention is preserved. Some would call this
 
15
"``mainline``" or "``dev``", and people from CVS often refer to this as "``HEAD``".
 
16
 
 
17
.. contents::
 
18
 
 
19
 
 
20
"SVN-Style" (``trunk/``, ``branches/``)
 
21
=======================================
 
22
 
 
23
Most people coming from SVN will be familiar with their "standard" project layout. 
 
24
Which is to layout the repository as::
 
25
 
 
26
  repository/       # Overall repository
 
27
   +- trunk/        # The mainline of development
 
28
   +- branches/     # A container directory
 
29
   |   +- foo/      # Branch for developing feature foo
 
30
   |     ...
 
31
   +- tags/         # Container directory
 
32
       +- release-X # A branch specific to mark a given release version
 
33
          ...
 
34
 
 
35
With Bazaar, that is a perfectly reasonable layout. 
 
36
It has the benefit of being familiar to people coming from SVN, 
 
37
and making it clear where the development focus is.
 
38
 
 
39
When you have multiple projects in the same repository, 
 
40
the SVN layout is a little unclear what to do.
 
41
 
 
42
 
 
43
``project/trunk``
 
44
~~~~~~~~~~~~~~~~~
 
45
 
 
46
The preferred method for SVN seems to be to give each project a top level directory for a layout like::
 
47
 
 
48
  repository/            # Overall repository
 
49
   +- project1/          # A container directory
 
50
   |   +- trunk/         # The mainline of development of project1
 
51
   |   +- branches/      # A container directory
 
52
   |       +- foo/       # Branch for developing feature foo of project1
 
53
   |         ...
 
54
   |
 
55
   +- project2/          # Container for project2
 
56
       +- trunk/         # Mainline for project2
 
57
       +- branches/      # Container for project2 branches
 
58
 
 
59
 
 
60
This also works with Bazaar. 
 
61
However, with Bazaar repositories are cheap to create 
 
62
(a simple ``bzr init-repo`` away), and their primary benefit is when the
 
63
branches share a common ancestry.
 
64
 
 
65
So the preferred way for Bazaar would be::
 
66
 
 
67
    project1/          # A repository for project1
 
68
     +- trunk/         # The mainline of development of project1
 
69
     +- branches/      # A container directory
 
70
         +- foo/       # Branch for developing feature foo of project1
 
71
           ...
 
72
    
 
73
    project2/          # A repository for project2
 
74
     +- trunk/         # Mainline for project2
 
75
     +- branches/      # Container for project2 branches
 
76
 
 
77
 
 
78
``trunk/project``
 
79
~~~~~~~~~~~~~~~~~
 
80
 
 
81
There are also a few projects who use this layout in SVN::
 
82
 
 
83
  repository/             # Overall repository
 
84
    +- trunk/             # A container directory
 
85
    |   +- project1       # Mainline for project 1
 
86
    |   +- project2       # Mainline for project 2
 
87
    |         ...
 
88
    |
 
89
    +- branches/          # Container
 
90
        +- project1/      # Container (?)
 
91
        |   +- foo        # Branch 'foo' of project1
 
92
        +- project2/
 
93
            +- bar        # Branch 'bar' of project2
 
94
 
 
95
 
 
96
A slight variant is::
 
97
 
 
98
  repository/             # Overall repository
 
99
    +- trunk/             # A container directory
 
100
    |   +- project1       # Mainline for project 1
 
101
    |   +- project2       # Mainline for project 2
 
102
    |         ...
 
103
    |
 
104
    +- branches/          # Container
 
105
        +- project1-foo/  # Branch 'foo' of project1
 
106
        +- project2-bar/  # Branch 'bar' of project2
 
107
 
 
108
I believe the reason for this in SVN, is so that someone 
 
109
can checkout all of "``trunk/``" and get the all the mainlines for all projects.
 
110
 
 
111
This layout can be used for Bazaar, but it is not generally recommended.
 
112
 
 
113
 1) ``bzr branch/checkout/get`` is a single branch at a time. 
 
114
    So you don't get the benefit of getting all mainlines with a single command. [1]_
 
115
 
 
116
 2) It is less obvious of whether ``repository/trunk/foo`` is the ``trunk`` of project 
 
117
    ``foo`` or it is just the ``foo`` directory in the ``trunk`` branch.
 
118
    Some of this confusion is due to SVN, because it uses the same "namespace" 
 
119
    for files in a project that it uses for branches of a project.
 
120
    In Bazaar, there is a clear distinction of what files make up a project, versus
 
121
    the location of the Branch. (After all, there is only one ``.bzr/`` directory per branch,
 
122
    versus many ``.svn/`` directories in the checkout).
 
123
 
 
124
.. [1] Note: `NestedTreeSupport`_ can provide a way to create "meta-projects" which
 
125
    aggregate multiple projects regardless of the repository layout.
 
126
    Letting you ``bzr checkout`` one project, and have it grab all the necessary
 
127
    sub-projects.
 
128
 
 
129
 
 
130
 
 
131
Nested Style (``project/branch/sub-branch/``)
 
132
=============================================
 
133
 
 
134
Another style with Bazaar, which is not generally possible in SVN
 
135
is to have branches nested within each-other.
 
136
This is possible because Bazaar supports (and recommends) creating repositories
 
137
with no working trees (``--no-trees``).
 
138
With a ``--no-trees`` repository, because the working files are not intermixed with
 
139
your branch locations, you are free to put a branch in whatever namespace you want.
 
140
 
 
141
One possibility is::
 
142
 
 
143
  project/             # The overall repository, *and* the project's mainline branch
 
144
   + joe/              # Developer Joe's primary branch of development
 
145
   |  +- feature1/     # Developer Joe's feature1 development branch
 
146
   |  |   +- broken/   # A staging branch for Joe to develop feature1
 
147
   |  +- feature2/     # Joe's feature2 development branch
 
148
   |    ...
 
149
   + barry/            # Barry's development branch
 
150
   |  ...
 
151
   + releases/
 
152
      +- 1.0/
 
153
          +- 1.1.1/
 
154
 
 
155
The idea with this layout is that you are creating a hierarchical layout for branches. 
 
156
Where changes generally flow upwards in the namespace. It also gives people a little
 
157
corner of the namespace to work on their stuff.
 
158
One nice feature of this layout, is it makes branching "cheaper" because it gives you
 
159
a place to put all the mini branches without cluttering up the global ``branches/`` namespace.
 
160
 
 
161
The other power of this is that you don't have to repeat yourself when specifying more detail in the
 
162
branch name.
 
163
 
 
164
For example compare::
 
165
 
 
166
  bzr branch http://host/repository/project/branches/joe-feature-foo-bugfix-10/
 
167
 
 
168
Versus::
 
169
  
 
170
  bzr branch http://host/project/joe/foo/bugfix-10
 
171
 
 
172
 
 
173
Also, if you list the ``repository/project/branches/`` directory you might see something like::
 
174
 
 
175
  barry-feature-bar/
 
176
  barry-bugfix-10/
 
177
  barry-bugfix-12/
 
178
  joe-bugfix-10/
 
179
  joe-bugfix-13/
 
180
  joe-frizban/
 
181
 
 
182
Versus having these broken out by developer. 
 
183
If the number of branches are small, ``branches/`` has the nice advantage
 
184
of being able to see all branches in a single view.
 
185
If the number of branches is large, ``branches/`` has the distinct disadvantage
 
186
of seeing all the branches in a single view (it becomes difficult to find the
 
187
branch you are interested in, when there are 100 branches to look through).
 
188
 
 
189
Nested branching seems to scale better to larger number of branches.
 
190
However, each individual branch is less discoverable. 
 
191
(eg. "Is Joe working on bugfix 10 in his feature foo branch, or his feature bar branch?")
 
192
 
 
193
One other small advantage is that you can do something like::
 
194
 
 
195
   bzr branch http://host/project/release/1/1/1
 
196
  or
 
197
   bzr branch http://host/project/release/1/1/2
 
198
 
 
199
To indicate release 1.1.1 and 1.1.2. This again depends on how many releases you have 
 
200
and whether the gain of splitting things up outweighs the ability to see more at a glance.
 
201
 
 
202
 
 
203
Sorted by Status (``dev/``, ``merged/``, ``experimental/``)
 
204
===========================================================
 
205
 
 
206
One other way to break up branches is to sort them by their current status.
 
207
So you would end up with a layout something like::
 
208
 
 
209
  project/               # Overall layout
 
210
   +- trunk/             # The development focus branch
 
211
   +- dev/               # Container directory for in-progress work
 
212
   |   +- joe-feature1   # Joe's current feature-1 branch
 
213
   |   +- barry-bugfix10 # Barry's work for bugfix 10
 
214
   |    ...
 
215
   +- merged/            # Container indicating these branches have been merged
 
216
   |   +- bugfix-12      # Bugfix which has already been merged.
 
217
   +- abandonded/        # Branches which are considered 'dead-end'
 
218
 
 
219
 
 
220
This has a couple benefits and drawbacks.
 
221
It lets you see what branches are actively being developed on, which is usually
 
222
only a small number, versus the total number of branches ever created.
 
223
Old branches are not lost (versus deleting them), but they are "filed away",
 
224
such that the more likely you are to want a branch the easier it is to find. 
 
225
(Conversely, older branches are likely to be harder to find).
 
226
 
 
227
The biggest disadvantage with this layout, is that branches move around.
 
228
Which means that if someone is following the ``project/dev/new-feature`` branch,
 
229
when it gets merged into ``trunk/`` suddenly ``bzr pull`` doesn't mirror the branch
 
230
for them anymore because the branch is now at ``project/merged/new-feature``.
 
231
There are a couple ways around this. One is to use HTTP redirects to point people
 
232
requesting the old branch to the new branch. ``bzr`` >= 0.15 will let users know
 
233
that ``http://old/path redirects to http://new/path``. However, this doesn't help
 
234
if people are accessing a branch through methods other than HTTP (SFTP, local filesystem, etc).
 
235
 
 
236
It would also be possible to use a symlink for temporary redirecting (as long as the symlink
 
237
is within the repository it should cause little trouble). However eventually you want to
 
238
remove the symlink, or you don't get the clutter reduction benefit.
 
239
Another possibility instead of a symlink is to use a ``BranchReference``. It is currently
 
240
difficult to create these through the ``bzr`` command line, but if people find them useful
 
241
that could be changed.
 
242
This is actually how `Launchpad`_ allows you to ``bzr checkout https://launchpad.net/bzr``.
 
243
Effectively a ``BranchReference`` is a symlink, but it allows you to reference any other URL.
 
244
If it is extended to support relative references, it would even work over http, sftp, 
 
245
and local paths.
 
246
 
 
247
.. _Launchpad: https://launchpad.net
 
248
 
 
249
 
 
250
Sorted by date/release/etc (``2006-06/``, ``2006-07/``, ``0.8/``, ``0.9``)
 
251
==========================================================================
 
252
 
 
253
Another method of allowing some scalability while also allowing the
 
254
browsing of "current" branches. Basically, this works on the assumption 
 
255
that actively developed branches will be "new" branches, and older branches
 
256
are either merged or abandoned.
 
257
 
 
258
Basically the date layout looks something like::
 
259
 
 
260
  project/                # Overall project repository
 
261
   +- trunk/              # General mainline
 
262
   +- 2006-06/            # containing directory for branches created in this month
 
263
   |   +- feature1/       # Branch of "project" for "feature1"
 
264
   |   +- feature2/       # Branch of "project" for "feature2"
 
265
   +- 2005-05/            # Containing directory for branches create in a different month
 
266
       +- feature3/
 
267
       ...
 
268
 
 
269
This answers the question "Where should I put my new branch?" very quickly.
 
270
If a feature is developed for a long time, it is even reasonable to copy a
 
271
branch into the newest date, and continue working on it there.
 
272
Finding an active branch generally means going to the newest date, and
 
273
going backwards from there. (A small disadvantage is that most directory
 
274
listings sort oldest to the top, which may mean more scrolling).
 
275
If you don't copy old branches to newer locations, it also has the disadvantage
 
276
that searching for a branch may take a while.
 
277
 
 
278
Another variant is by release target::
 
279
 
 
280
  project/          # Overall repository
 
281
   +- trunk/        # Mainline development branch
 
282
   +- releases/     # Container for release branches
 
283
   |   +- 0.8/      # The branch for release 0.8
 
284
   |   +- 0.9/      # The branch for release 0.9
 
285
   +- 0.8/          # Container for branches targeting release 0.8
 
286
   |   +- feature1/ # Branch for "feature1" which is intended to be merged into 0.8
 
287
   |   +- feature2/ # Branch for "feature2" which is targeted for 0.8
 
288
   +- 0.9/
 
289
       +- feature3/ # Branch for "feature3", targeted for release 0.9
 
290
 
 
291
 
 
292
Some possible variants include having the ``0.9`` directory imply
 
293
that it is branched *from* 0.9 rather than *for* 0.9, or having the ``0.8/release``
 
294
as the official release 0.8 branch.
 
295
 
 
296
The general idea is that by targeting a release, you can look at what branches are
 
297
waiting to be merged. It doesn't necessarily give you a good idea of what the
 
298
state of the branch (is it in development or finished awaiting review).
 
299
It also has a history-hiding effect, and otherwise has the same benefits 
 
300
and deficits as a date-based sorting. 
 
301
 
 
302
 
 
303
Simple developer naming (``project/joe/foo``, ``project/barry/bar``)
 
304
====================================================================
 
305
 
 
306
Another possibly layout is to give each developer a directory, and then
 
307
have a single sub-directory for branches. Something like::
 
308
 
 
309
  project/      # Overall repository
 
310
   +- trunk/    # Mainline branch
 
311
   +- joe/      # A container for Joe's branches
 
312
   |   +- foo/  # Joe's "foo" branch of "project"
 
313
   +- barry/
 
314
       +- bar/  # Barry's "bar" branch of "project"
 
315
 
 
316
The idea is that no branch is "nested" underneath another one, just that each developer
 
317
has his/her branches grouped together.
 
318
 
 
319
A variant which is used by `Launchpad`_ is::
 
320
 
 
321
  repository/
 
322
   +- joe/             # Joe's branches
 
323
   |   +- project1/    # Container for Joe's branches of "project1"
 
324
   |   |   +- foo/     # Joe's "foo" branch of "project1"
 
325
   |   +- project2/    # Container for Joe's "project2" branches
 
326
   |       +- bar/     # Joe's "bar" branch of "project2"
 
327
   |        ...
 
328
   |
 
329
   +- barry/
 
330
   |   +- project1/    # Container for Barry's branches of "project1"
 
331
   |       +- bug-10/  # Barry's "bug-10" branch of "project1"
 
332
   |   ...
 
333
   +- group/
 
334
       +- project1/
 
335
           +- trunk/   # The main development focus for "project1"
 
336
 
 
337
 
 
338
This lets you easily browse what each developer is working on. Focus branches
 
339
are kept in a "group" directory, which lets you see what branches the "group"
 
340
is working on.
 
341
 
 
342
This keeps different people's work separated from each-other, but also makes it
 
343
hard to find "all branches for project X". `Launchpad`_ compensates for this
 
344
by providing a nice web interface with a database back end, which allows a
 
345
"view" to be put on top of this layout.
 
346
This is closer to the model of people's home pages, where each person has a
 
347
"``~/public_html``" directory where they can publish their own web-pages.
 
348
In general, though, when you are creating a shared repository for centralization
 
349
of a project, you don't want to split it up by person and then project.
 
350
Usually you would want to split it up by project and then by person.
 
351
 
 
352
 
 
353
Summary
 
354
=======
 
355
 
 
356
In the end, no single naming scheme will work for everyone. It depends a lot on
 
357
the number of developers, how often you create a new branch, what sort of
 
358
lifecycles your branches go through. Some questions to ask yourself:
 
359
 
 
360
  1) Do you create a few long-lived branches, or do you create lots of "mini" feature branches
 
361
     (Along with this is: Would you *like* to create lots of mini feature branches, but can't
 
362
     because they are a pain in your current VCS?)
 
363
 
 
364
  2) Are you a single developer, or a large team?
 
365
 
 
366
  3) If a team, do you plan on generally having everyone working on the same branch at the same
 
367
     time? Or will you have a "stable" branch that people are expected to track.
 
368