threads / discuss / 936

Semantics for one step undo/redo

Subject: Semantics for one step undo/redo

## tl;dr

3 messages between Jun 14, 2005 and Jun 14, 2005.

replies: 2people: 2as markdown or json

Jon Seymour· Jun 14, 2005, 13:50 UTC · lore
Hi.

I've implemented some undo/redo scripts which I am testing in my own workspace before I unleash them on an wider audience. However, I thought it would be useful to discuss the semantics of my approach on the list.

The approach focuses on one-step undo, redo. What I mean by this is that a given undo or redo operation can undo or redo exactly one commit. Of course, it is possible to compose arbitrary sequences of undo and redos with the expected results. I regard multi-commit undos/redos to be a special case of the one-step undo/redo and so can be neglected for the purposes of discussion.

UNDO Semantics:
    When the working tree and cache are synced with a commit, C, then
undo has the effect of returning the workspace to the state
immediately prior to the commit C.
UNDO Pre-conditions:
    - the working tree matches the cache (git-update-cache --refresh
exits with zero)
    - the cache matches the tree specified by HEAD or UNDONE_HEAD
UNDO Post-conditions
    - UNDONE_HEAD is set to the value of HEAD
    - HEAD is replaced by its left-most parent
    - HEAD's commit message is written to .nextmsg
    - the workspace tree and cache is unchanged
    - an entry containing the UNDONE_HEAD head and its parents are
written to the end git/redo-log

A tweak to the undo implementation would be to allow the user to specify which merge branch to undo down.

REDO Semantics
    - redo will replay a previous commit but any or all of the tree,
the parents, the message may be replaced by edited values.
REDO Pre-conditions:
    - at least one entry exists in the .git/redo-log
    - the cache matches the working tree
    - .nextmsg contains the commit message
    - HEAD contains the commit id of the current predecessor (which
may differ from the logged value)
REDO Post-conditions:
    - the working tree is committed with .nextmsg as its message, the
first parent replaced by HEAD and the remaining parents read from .the
tail of .git/redo-log
    - .nextmsg is cleared
    - the last line of .git/redo-log is removed

With the scripts I have written, I can fix a commit message, 4 messages old with:

undo
undo
undo
undo
vi .nextmsg
while redo
do
      echo done
done

I think my approach differs a little from Junio's (but I haven't analysed his deeply) in that the redolog is actually just the slightly edited output of git-rev-list --merge-order --parents head base [ the edits removes from the list the parallel branches that aren't actually involved in the undo ]

Comments?
jon.
-- 
homepage: http://www.zeta.org.au/~jon/
blog: http://orwelliantremors.blogspot.com/
Jon Seymour· Jun 14, 2005, 13:54 UTC · re: Jon Seymour · lore

Re: Semantics for one step undo/redo

Sorry, I omitted an important aspect of REDO Post-conditions - corrected below
Show 17 quoted lines
> REDO Semantics
>     - redo will replay a previous commit but any or all of the tree,
> the parents, the message may be replaced by edited values.
> 
> REDO Pre-conditions:
>     - at least one entry exists in the .git/redo-log
>     - the cache matches the working tree
>     - .nextmsg contains the commit message
>     - HEAD contains the commit id of the current predecessor (which
> may differ from the logged value)
> 
> REDO Post-conditions:
>     - the working tree is committed with .nextmsg as its message, the
> first parent replaced by HEAD and the remaining parents read from .the
> tail of .git/redo-log
>     - .nextmsg is cleared
>     - the last line of .git/redo-log is removed
additional post-conditions:
     - the diff between the old head and its old parent (as read from
the log) is applied to the workspace and cache.
     - if the re-applied diff fails, the workspace and cache are
returned back to the state immediately following the previous commit
and the user has the chance to manually reapply the diffs before
updating the index into a state that allows further redos
jon.
Junio C Hamano· Jun 14, 2005, 15:01 UTC · re: Jon Seymour · lore

Re: Semantics for one step undo/redo

>>>>> "JS" == Jon Seymour <jon.seymour@gmail.com> writes:

JS> I think my approach differs a little from Junio's (but I haven't JS> analysed his deeply) in that the redolog is actually just the slightly JS> edited output of git-rev-list --merge-order --parents head base [ the JS> edits removes from the list the parallel branches that aren't actually JS> involved in the undo ]

JS> Comments?

I've only took a brief glance at your description and found it quite sensible. I did not find anything majorly wrong.

If you are talking about jit-rewind (I think the message I told you about it was not sent to the list, so the list audience may not know about it, by the way), there is not much to analyze.

It populates the snapshot pool with the commits in the specified commit chain, and after that it is totally up to the user what to do with them, hence there is no redo semantics attached to it. JIT way of doing things is generally more dangerous in that it gives you so much more flexibility that it lets you freely shoot yourself in the foot ;-). When the core Plumbing side stabilizes I may revisit updating JIT to make certain parts of it not so sharp-edged, but I have been busy futzing with the Plumbing side lately, and having found not much need to change JIT, haven't done much about updating my own Porcelain.

← back to recent threads