[PATCH RFC] update: add an option to allow to merge local changes when crossing branches

Martin Geisler martin at geisler.net
Sat Feb 23 05:24:19 CST 2013

Kevin Bullock <kbullock+mercurial at ringworld.org> writes:

> On 22 Feb 2013, at 2:35 PM, Martin Geisler wrote:
>> Kevin Bullock <kbullock+mercurial at ringworld.org> writes:
>>> On 22 Feb 2013, at 7:24 AM, Laurens Holst wrote:
>>>> I’m not entirely clear why this isn’t the default? Any update with
>>>> local changes is performing a merge anyway (with all its risks for
>>>> conflicts), so why would updating across branches need to be
>>>> prohibited?
>>> Much greater likelihood of conflicts, and no way to get your local
>>> changes back if you want to bail.
>> We do save the original files when merging a dirty working copy into a
>> target revisioon -- 'hg resolve --tool internal:local' will give them
>> back to you even though they were never committed anywhere.
> Huh, how long have we been doing that? And more importantly, if we
> allowed a cross-branch update, how would you get them back _after
> updating back to your original place_?

We've been doing it for ages, but despite my best efforts, it keeps
surprising even very experienced users and developers :)

As for getting the dirty files back after updating somewhere and back
again, then it is a bit tricky. You need to make sure that your working
copy has the dirty files after the first update.

So after

  hg update $SOMEWHERE
  hg resolve --all --tool internal:local

the files look like they did in your dirty working copy. If you do

  hg update $BACK
  hg resove --all --tool internal:local

you will be back to where you started. If you modified the files after
the first update, then it is the modified version you see after the
second resolve.

>> I don't know why you say the risk of conflicts is greater here than
>> with any other update/merge?
> Simply because you're merging a larger set of changes, as you get to
> below.

As you say, a merge because of a dirty working copy will use

* working copy parent (base)
* dirty working copy  (local)
* update target       (other)

That ought to be an easy merge regardless of the update target since the
difference between base and local is "small".

I say "small" because I expect the diff present in the dirty working
copy to be one commit. That is much smaller than most branch merges
where the distance from local/other to base is 10, 100 or more commits.

>>> To update across branches, it would have to apply _all_ the changes
>>> between the common ancestor and the working copy, and write the
>>> result into the working copy. Thus the likelihood of clobbering
>>> uncommitted changes is much greater (and much more subject to
>>> operator error in your merge tool of choice).
>> I think you're saying that an update the crosses branches will tend
>> to "span" a greater range of revisions than an update that is linear.
>> That seems reasonable, but the underlying merge problem ought to be
>> the same as if you had done a linear update across a big span of
>> revisions.
> The theoretical problem is the same, but the _usability_ problem is
> very different, both because of a likely larger set of conflicts
> (merge early and often!), and because you'd have to do something
> different to get back to your original state (and we'd likely have to
> track more state outside of history).

The risk of losing changes is certainly greater when they only live
inside .hg/merge instead of in permanent history -- 100% agreed.

My starting point was only that every single time I've had the "sorry, I
wont help you update across branches" message I "fixed" it by updating
twice and could continue with my work.

Martin Geisler
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: <http://selenic.com/pipermail/mercurial-devel/attachments/20130223/b99ffae7/attachment.pgp>

More information about the Mercurial-devel mailing list