[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: Checkpointing mock-up option 3 (backed by a local repo)

From: Nathan Hartman <hartman.nathan_at_gmail.com>
Date: Mon, 7 Aug 2017 16:54:15 -0400

On Tue, Aug 1, 2017 at 9:19 AM, Julian Foad <julianfoad_at_apache.org> wrote:
> Keep in mind that a revision -- or any versioned state -- can be
> thought of in two ways: as a complete snapshot of the tree, or as
> representing a change relative to the previous snapshot.
>
> First let us be sure we understand that updating *is* rebasing. To
> explain this, think about a plain WC with no checkpointing. The WC
> has a base tree and a working tree. The work you do in a working copy
> is to create a change based on the base. An 'update' is a request to
> update the base and also to adjust the working version so that it
> represents the 'same' change that it previously did, except the
> change is now against the new base. Hence update is 'rebasing' your
> local change. The adjustment of the old change (against the old base)
> to a new change (against the new base) is accomplished by a merge.
>
> Illustration: a plain old WC based on r20 is like a one-commit local
> branch based on r20.
>
> [ repo -----(r10)------(r20)------(r30)------(r40)---
> [ ||
> [ ||
> [ WC (BASE)-(WORK)
>
> [(X) represents a tree snapshot. WORK means the working/on-disk state
> in the WC, including what libsvn_wc calls 'actual'.]
>
> Updating to r30 involves merging (r20:30) with (rBASE:WORK) to create
> (WORK'), and setting the new base to r30.
>
> [ repo -----(r10)------(r20)------(r30)------(r40)---
> [ ||
> [ ||
> [ WC (BASE')-(WORK')

I appreciate that you've taken the time and effort to explain this,
complete with graphs. I suppose I should have known that an update
rebases the working copy onto the new revision, but for whatever reason
I was under the impression that it was the other way around, that the
incoming changes get applied on top of the working copy.

The only drawback of the rebase is that update is a one-way operation,
with no 'undo' mechanism. It's the only place in Subversion where you
could potentially lose a very particular configuration of your files,
which may have taken some tricky manipulations to arrive at, and the
nature of update (being the action that immediately precedes a commit)
is such that your intention was probably to save those bits, not change
them. Currently in such a situation, the user should mitigate that by a
svn copy to a new branch, or adopt a policy of branching for everything
and avoid this issue altogether. Personally I've been known to copy the
contents of my working copy to a temp directory before performing an
update, just in case. :-) But the premise of version control is that
you should never fear losing anything. That makes update the perfect
use case and showcase for a checkpoint feature, even if the user never
takes advantage of checkpoints otherwise.

Referring to this last graph:

> (b) Keep the existing checkpoints based on the older base, and bring
> in the new base to be used only for new checkpoints. For this
> illustration, assume we had no outstanding working changes before
> running the update. We merge the incoming changes with the *complete*
> checkpoint series and record the result as (Pn').
>
> [ repo -----(r10)------(r20)------(r30)------(r40)---
> [ || ||
> [ || ||
> [ | (P0) (P0')
> [ | \ \
> [ WC | \ \
> [ | \ \
> [ | (P1)-...-(Pn)--(Pn'=BASE)
> [ \
> [ \_(WORK')
>
> The WC now contains two "base" snapshots (P0 and P0') copied from the
> repository, and (n) checkpoint snapshots, and a merged checkpoint.

If checkpoints are implemented using a hidden repo, is it feasible to
place two directories, BASE and WORK, at its root, and save the BASE
with each checkpoint? If so, Subversion's atomic repo-wide commits
would automatically solve the issue of keeping each checkpoint
synchronized with its base, since both would be saved together. The
repo's temporal compression would mean that very little additional data
would be saved, in comparison to the size of BASE.

If this is feasible, then I would treat checkpoints as a sort of time
line, rather than a private branch. That is, each action against the
checkpoints, whether to create a new checkpoint, perform an update, or
rollback to an earlier checkpoint, would create a new checkpoint with
the contents of the current BASE and WORK. So, rolling *back* (to an
earlier, in time, checkpoint) could actually roll your BASE *forward*.
The beauty is that since both BASE and WORK are saved in the hidden
repo, no server connection is needed to roll back or forward through
the point of a BASE change.

Here's an illustration of what might happen over the course of a
workday:

Time | Action | Hidden Repo HEAD Contains
------|------------------|--------------------------------------------
08:00 | Initial Checkout | No hidden repo yet
08:30 | Checkpoint 1 | BASE 1 / WORK 1
09:00 | Checkpoint 2 | BASE 1 / WORK 2
09:30 | Checkpoint 3 | BASE 1 / WORK 3
10:00 | Update | BASE 1 / WORK 4 (saved prior to the update)
10:30 | Checkpoint 5 | BASE 2 / WORK 5
11:00 | Checkpoint 6 | BASE 2 / WORK 6
11:30 | Update | BASE 2 / WORK 7 (saved prior to the update)
12:00 | Checkpoint 8 | BASE 3 / WORK 8
12:30 | Rollback to 3 | BASE 1 / WORK 3
13:00 | Checkpoint 10 | BASE 1 / WORK 10
13:30 | Checkpoint 11 | BASE 1 / WORK 11
14:00 | Rollback to 8 | BASE 3 / WORK 8
14:05 | Update | No change (up-to-date with central repo)
14:10 | Commit | No change, or destroy hidden repo ???

Notice that at 12:30, rolling back to checkpoint 3 rolls back the BASE
to BASE 1, and at 14:00 rolling back to checkpoint 8 rolls the BASE
forward to BASE 3.

At 14:05 when the user invokes svn update, there are no uncheckpointed
changes in the WC and no new changes to fetch from central repo, so the
hidden repo HEAD does not move. (No checkpoint is made.)

At 14:10 when the user performs svn commit, a case could be made to
keep the hidden repo intact (rolling back through the point of commit
would create a new checkpoint, just like the operations shown above) or
to destroy the hidden repo (to prevent it from growing without bound).
There could be quite a bit of debate around this question. I would
contend that it should not be destroyed, until the user issues a
command to do so. Perhaps there are additional states in the timeline
that the user wants to commit, or perhaps rollback to and continue
working on.
Received on 2017-08-07 22:54:27 CEST

This is an archived mail posted to the Subversion Dev mailing list.