Checkouts and Bound Branches
This is not documentation about how bzr works. This is sketchings of one person's mental model about how bzr maybe should work.
When speaking of bound branches, the terms 'local' and 'remote' is used to denote the roles of "branch which is bound" and "branch it's bound to". They don't necessarily imply any spatial or network topological arrangement, only the logical relationship between them.
Definitions and Differences
A Branch is a line of development.
A Checkout is a working tree on a Branch.
A Bound Branch is a Branch that is tied to another Branch, such that commits on it will generally also be sent to the other.
Query: Should binding also imply lockstep, so that a commit can't be made if the remote bound location has changes the local doesn't? Don't kneejerk; current setup is at least partly biased due to conflation.
Extra on Checkouts
Checkouts can subdivide into two types; Heavy and Light. Light are just the working tree, with the minimal metadata that comes with. Heavy include a local cache of [some portion of] the revision history, used to speed up operations.
Heavy checkouts can also, by virtue of having that extra data, be lazy. With the full history cached, many operations like log and diff and nick and even being a source for branch can be done without talking to the remote branch (which is often on a different server). Now, you may have obsolete data, as old as your last update or commit or some other command that necessarily checks you against the remote. For many workflows, that's an acceptable limitation for the gain of not waiting on the network.
So the fundamental difference between the two is that when you create a Checkout, you have one branch. When you create a Bound Branch, you have two branches. They're arranged so that (assuming 'yes' to lockstep query) they are by default generally kept in sync, but they are still conceptually and availably independent branches.
With a Checkout, contrarily, there's only one Branch. No matter how many Checkouts you create on a given Branch, there's still only one Branch.
Consequences and Changes to Current UI
Leaving to one side discussion about its appropriateness to remain an option, commit --local is a sensible thing to do with bound branches. It makes no sense at all on a checkout; commits have to go on a branch, and there's only one branch for them to go to. (that last is slightly a lie, but the way in which it's a lie doesn't change the analysis given)
Similarly, unbind makes perfect sense with a bound branch. With a checkout, not so; there's nothing locally to unbind.
- A Bound Branch would have separate sets of saved locations (parent, push, etc) independently on the local and remote sides. A Checkout would only have one set (since there's only one Branch).
update should not be a command that gets much use with bound branches. In particular, it is the wrong command to use for the conceptual operation "catch my local branch up with changes from the branch it's bound to". We already have commands to move revisions between branches and shift head revs appropriately; those are pull and push. We should add a sync command to run it both ways.
update is a command that has to do with syncing a working tree up to its branch. Running update in a bound branch should do just what it does in any other branch; update's the working tree to match its branch (which is the local branch sitting there; no contact with the remote is needed or should happen).
Now, a command is needed to do the "magic" that update does for moving your local commit over to the right-hand side of a merge onto the remote side. But abusing update for this is totally the wrong path. In general, aside from this bound/checkout issue totally, merge should have a --pivot or --complement or --bikeshed option to do that, since you may want to do so anywhere. Perhaps the above-mentioned sync command should do that.
A bound branch can do a passably good job of standing in for a heavy checkout. It's gotten us this far, after all. A heavy checkout, in concept, is not capable of standing in for a bound branch.
There's no reason the implementation of a [heavy] checkout can't be built on a bound branch. But it needs to have a flag to tell the UI that it's a checkout, not a bound branch, so that it can behave appropriately.