how to revert update operation
Aaron Bentley
aaron.bentley at utoronto.ca
Wed Jul 19 14:23:22 BST 2006
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Robert Collins wrote:
> On Tue, 2006-07-18 at 12:17 -0400, Aaron Bentley wrote:
>>It should be illegal for wt.basis_tree() to be a non-ancestor of
>>wt.branch.basis_tree(), so that part of the comment seems spurious.
>>Similarly, wt.basis_tree() is an ancestor of wt.
>
>
> Not at all. Take a branch, make two lightweight checkouts, commit in on,
> update in the other, uncommit while you are there, then do a new commit.
> Now go to the other light checkout, and the tree's basis_tree is not an
> ancestory of the branch's basis_tree.
Yes, and you are now in an illegal state that we explicitly don't
handle. Uncommit is a power tool, and it's possible to cut your fingers
off using it.
If you try to preserve the ancestry for working tree, you're now
starting to treat the working tree like a branch.
>>Furthermore, it's not at all clear to me that the user wants the
>>branch.last_revision() to be merged with the master. If they have a
>>bound branch, and their working tree is out of date with the branch,
>>this suggests that someone else has committed or pushed into the branch.
>> They may not be aware of these new revisions, and they certainly
>>wouldn't have reviewed them, since they're not the current tree state.
>
>
> For shared branches, the 'review before I accept it' workflow is not
> present. If users want to do that they should not be using a shared
> branch.
There is a big difference between applying the changes that are present
in the master branch, and applying the changes that are present in the
local branch. They are two different locations, and may have different
access controls.
Users don't mean 'apply the local branch changes' when they update, they
mean 'apply the master branch changes'. So it is surprising behaviour
to apply the local branch changes.
I can't think of a good reason why both the checkout and the local
branch would be out of date at the same time. But here are some bad
reasons:
$ bzr unbind
# --local hasn't been implemented for uncommit, but AIUI, the plan is to
# do so.
$ bzr uncommit --local
$ bzr bind foo
$ bzr update
It's pretty clear that the user didn't want to commit those changes to
the master branch, so in this scenario, applying the local branch
changes is The Wrong Thing.
Here's another:
$ cp -r foo bar
$ cd bar
$ bzr commit -m 'created new branch'
$ cd ../foo
$ bzr update
In this scenario, the user intended to create a new branch, but foo is
actually a lightweight checkout, so bar is a checkout of the same branch.
Again, applying the local changes is The Wrong Thing.
Here's another:
A cracker does:
$ bzr commit -m "add malicious code"
$ bzr push sftp://example.com/home/some_honest_user/myproj
An honest user does
$ ssh example.com
$ cd myproj
$ bzr update
$ bzr commit -m "Add my latest, harmless changes"
Generating OpenSSH signature
Please enter your passphrase:
Committed revno 76
The user knows that all the commits on the master branch are signed, and
he has a checking rule, so he is confident that update can never
introduce unsigned code into his tree. He is wrong, and the cracker has
now caused a signed commit containing malicious code to be generated.
Again, The Wrong Thing.
So, whether the vector is uncommit, cp -r or push, auto-applying the
local branch changes can be the wrong thing.
>>So, I think if the master branch is defined, and the wt.last_revision()
>>!= branch.last_revision(), you're in an error condition. We should
>>explain the situation to the user, and get them to run either update
>>- --checkout, (update checkout to the last revision in the branch), or
>>update --branch...
>
>
> Well, we could do that, but I think its just exposing machinery to the
> user for no good reason.
> Perhaps I'm missing something?
My point is that this is a strange situation to encounter. I don't
think we can know what the user intent is, but if I had to guess, I
would uncommit the local branch changes, and apply the master changes,
because I think that is what the user is expecting.
But since uncommit is dangerous, we can't do that.
On the other hand, we can't just automatically do a double merge,
because update is a destructive operation, and so it's very bad to guess
wrong.
Finally, there's the issue of conflicts.
I don't think it's valid to perform two operations in a row when each
may produce conflicts. But I'll address that in our "Status should not
special case conflicts" discussion.
What I will say here is that, if we assume it's valid to do a merge when
we already have conflicts, it's still not a nice thing to do. Conflicts
are often confusing, and it's nicest to deal with them in bite-sized
pieces. Conflicts on top of conflicts is even more confusing, and, in
some cases, impossible to represent with out current conflict types.
So, if the first update will produce conflicts, I think it's nicer to
stop and ask the user to resolve the conflicts, before doing a second
merge operation.
Aaron
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org
iD8DBQFEvjJK0F+nu1YWqI0RAlc2AJ966PiXrRSPKqnVpR29EUTnDJEdzACfQ8hd
K7IH0cwV/I5y2mjrectzJ68=
=kl16
-----END PGP SIGNATURE-----
More information about the bazaar
mailing list