What I've learned from scmproj (Re: what should be done to merge nested trees patch to bzr-core?)

Alexander Belchenko bialix at ukr.net
Thu Jun 16 10:41:16 UTC 2011


Martin Pool пишет:
> What did you learn from scmproj etc?

I will put as much of other important things about working with 
nested-trees-like projects. Also I want to note that both scmproj and 
bzr-externals have a lot in common, but I think bzr-externals is easier 
to use just because it hooks in existing commands via various hooks, 
while scmproj provides you a set of special commands to work with a 
project. I think bzr-externals is better suited for centralized 
(lock-step) development model and it seamlessly integrated into GUIs.
But it has its own flaw: it's hard to disable its recursive operations 
if you want to. With scmproj you have much more fine-grained control 
over what do you do.

1) Recursive operations and composite checkout.

a) Commit in the project root should be recursive most of the time, to 
make sure you have committed consistent project state, and you can 
restore that same state later. That's the most important point, if you 
don't need to have ability to restore the exact past state of your 
project you can live without it.

Both scmproj and bzr-externals save revision-ids of nested components in 
the root tree as plain text file, so in the case of recursive commit 
they should invoke commits in backward order -- from deepest components 
up to the root component. The same applied to nested trees design too: 
in order to be able store link to revision of nested branch you should 
invoke commit in that branch first.

Scmporj uses separate command to perform project-wide commit. It's 
important to use it to make sure snapshot of the project updated properly.

b) Status/diff -- it will be nice to have them recursive, but in the 
case of too many nested components (we have one project here with such 
problem) it becomes noticeable slow. So we're using project-wide 
status/diff only before project-wide commit, and can live with 
non-recursive behavior most of the time.

Also for status is very important thing is to provide a note when nested 
components have been committed without committing the root component, so 
you should know that you should perform project-wide commit in order to 
record new state of components (update the snapshot). That's very very 
important, and I think it should be pretty fast to check and print to 
the user. Currently I've managed to emulate it in scmproj trunk with 
pnew alias, so I can see missing-like report for components relative to 
their snapshotted state. So based on this info I can inspect which 
components are out-of-snapshot. (But I can't hook this into 
project-status alias yet).

c) Export -- really should be recursive, we don't have that yet, at 
least not for tar/gz/zip. I think it should work for exporting in the 
plain directory though.

d) Push/pull/update/merge/missing -- most of the time you want them 
recursive, but beware of feature branches!!! You should be careful to 
push into proper location, that's the pain point right now.

e) Uncommit -- very hard thing to do it properly. You don't want it to 
be blindly recursive, but you'd better have it recursive and uncommit 
what have been committed. So, if you committed root and component A, but 
component B is not changed, then on uncommit of root you also want to 
uncommit A, but not B for obvious reasons. The reverse is also true: on 
uncommit in A you also will want to uncommit in root, because it will 
have recorded revision-id of uncommitted revision in component A.

The things will faster becomes too tricky to handle if you want uncommit 
B. In this case you may want to uncommit root too, down to the point 
when revision of B has been recorded. And it may trigger uncommits in 
other components to the same level. It will be too destructive, IMO. But 
otherwise you'll have inconsistent tree, in any case. I think uncommit 
itself should be prohibited in nested trees, just because it might 
destroy too much. Where you will find uncommitted revision pointed to by 
project root in general? That's very very tricky.

I don't have any answer on this problem. But I think that problem is 
somewhat similar to problem with tags pointing to revision outside the 
branch history.
But if you can't use tag you won't loose too much. But if you're unable 
to checkout your past state of the project because there is no revision 
stored in snapshot, what will you do? That's complete inrecoverable failure.

Currently when I need to uncommit something in the project locally, I 
should tread very very carefully. And I think in general case it's much 
better to just make a reverse merge.

f) Another case similar to uncommit is `pull --overwrite` in the 
component tree may turn the history backward, thus effectively 
destroying it.  The consequences will be the same as with uncommit -- 
you simply won't be able to restore the past state of your project. 
Therefore you should never ever do that.

2) Composite history.

Currently I don't see (or don't understand) how can you get the 
composite log for the entire project. I can imagine that history of 
components could be shown as virtual merge points when root component 
has recorded revision ids of nested components. That will be really 
good, but I'm not sure about performance of such approach. Maybe it will 
be good enough to be usable.

In general I'd like to have recursive qlog by default.

But beware of uncommits and `pull --overwrite` -- they may destroy the 
history and therefore you won't be able to see composite log.

3) Other things

.bzrignore from nested components should be used in recursive 
status/diff/add operations. Most of the time they are used, at least in 
scmproj, but that should not be regressed with real nested trees.


and Last note.

As I wrote in my other mail about feature branches and their problems, I 
think bzr should store everything in the root component branch. In the 
end we have nice shared repositories mechanics, so duplicates of the 
components won't necessarily bloat you server storage. The separate 
component branches and branches integrated into projects may live in the 
same shared repository.

But as I think further, I come to conclusion that the best nested trees 
can be obtained if we just merge components into root component. This 
will automatically solve a lot of highlighted problems. But it will 
create a new problem: how to extract the component then? Share changes 
between projects using the same component?

I have some ideas about that, but as I can see they cannot be 
implemented within bzr model.

I hope my story will be useful.

-- 
All the dude wanted was his rug back



More information about the bazaar mailing list