{"thread":{"id":"936","subject":"Semantics for one step undo/redo","startedAt":"2005-06-14T13:50:02Z","lastAt":"2005-06-14T15:01:16Z","messageCount":3,"participants":["Jon Seymour","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"4945","messageId":"2cfc403205061406507af5a66@mail.gmail.com","threadId":"936","inReplyTo":null,"subject":"Semantics for one step undo/redo","fromName":"Jon Seymour","fromEmail":"jon.seymour@gmail.com","sentAt":"2005-06-14T13:50:02Z","receivedAt":"2005-06-14T13:50:02Z","isPatch":false,"sender":{"key":"jon.seymour@gmail.com","avatar":"https://avatars.githubusercontent.com/u/207131?v=4"},"body":"Hi.\n\nI've implemented some undo/redo scripts which I am testing in my own\nworkspace before I unleash them on an wider audience. However, I\nthought it would be useful to discuss the semantics of my approach on\nthe list.\n\nThe approach focuses on one-step undo, redo. What I mean by this is\nthat a given undo or redo operation can undo or redo exactly one\ncommit. Of course, it is possible to compose arbitrary sequences of\nundo and redos with the expected results. I regard multi-commit\nundos/redos to be a special case of the one-step undo/redo and so can\nbe neglected for the purposes of discussion.\n\nUNDO Semantics:\n    When the working tree and cache are synced with a commit, C, then\nundo has the effect of returning the workspace to the state\nimmediately prior to the commit C.\n\nUNDO Pre-conditions:\n    - the working tree matches the cache (git-update-cache --refresh\nexits with zero)\n    - the cache matches the tree specified by HEAD or UNDONE_HEAD\n\nUNDO Post-conditions\n    - UNDONE_HEAD is set to the value of HEAD\n    - HEAD is replaced by its left-most parent\n    - HEAD's commit message is written to .nextmsg\n    - the workspace tree and cache is unchanged\n    - an entry containing the UNDONE_HEAD head and its parents are\nwritten to the end git/redo-log\n\nA tweak to the undo implementation would be to allow the user to\nspecify which merge branch to undo down.\n\nREDO Semantics\n    - redo will replay a previous commit but any or all of the tree,\nthe parents, the message may be replaced by edited values.\n\nREDO Pre-conditions:\n    - at least one entry exists in the .git/redo-log\n    - the cache matches the working tree\n    - .nextmsg contains the commit message\n    - HEAD contains the commit id of the current predecessor (which\nmay differ from the logged value)\n\nREDO Post-conditions:\n    - the working tree is committed with .nextmsg as its message, the\nfirst parent replaced by HEAD and the remaining parents read from .the\ntail of .git/redo-log\n    - .nextmsg is cleared\n    - the last line of .git/redo-log is removed\n\nWith the scripts I have written, I can fix a commit message, 4\nmessages old with:\n\nundo\nundo\nundo\nundo\nvi .nextmsg\nwhile redo\ndo\n      echo done\ndone\n\nI think my approach differs a little from Junio's (but I haven't\nanalysed his deeply) in that the redolog is actually just the slightly\nedited output of git-rev-list --merge-order --parents head base [ the\nedits removes from the list the parallel branches that aren't actually\ninvolved in the undo ]\n\nComments?\n\njon.\n-- \nhomepage: http://www.zeta.org.au/~jon/\nblog: http://orwelliantremors.blogspot.com/\n"},{"id":"4946","messageId":"2cfc4032050614065443119d5f@mail.gmail.com","threadId":"936","inReplyTo":"2cfc403205061406507af5a66@mail.gmail.com","subject":"Re: Semantics for one step undo/redo","fromName":"Jon Seymour","fromEmail":"jon.seymour@gmail.com","sentAt":"2005-06-14T13:54:17Z","receivedAt":"2005-06-14T13:54:17Z","isPatch":false,"sender":{"key":"jon.seymour@gmail.com","avatar":"https://avatars.githubusercontent.com/u/207131?v=4"},"body":"Sorry, I omitted an important aspect of REDO Post-conditions - corrected below\n\n> REDO Semantics\n>     - redo will replay a previous commit but any or all of the tree,\n> the parents, the message may be replaced by edited values.\n> \n> REDO Pre-conditions:\n>     - at least one entry exists in the .git/redo-log\n>     - the cache matches the working tree\n>     - .nextmsg contains the commit message\n>     - HEAD contains the commit id of the current predecessor (which\n> may differ from the logged value)\n> \n> REDO Post-conditions:\n>     - the working tree is committed with .nextmsg as its message, the\n> first parent replaced by HEAD and the remaining parents read from .the\n> tail of .git/redo-log\n>     - .nextmsg is cleared\n>     - the last line of .git/redo-log is removed\n\nadditional post-conditions:\n\n     - the diff between the old head and its old parent (as read from\nthe log) is applied to the workspace and cache.\n\n     - if the re-applied diff fails, the workspace and cache are\nreturned back to the state immediately following the previous commit\nand the user has the chance to manually reapply the diffs before\nupdating the index into a state that allows further redos\n\njon.\n"},{"id":"4949","messageId":"7voea93rur.fsf@assigned-by-dhcp.cox.net","threadId":"936","inReplyTo":"2cfc403205061406507af5a66@mail.gmail.com","subject":"Re: Semantics for one step undo/redo","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-06-14T15:01:16Z","receivedAt":"2005-06-14T15:01:16Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"JS\" == Jon Seymour <jon.seymour@gmail.com> writes:\n\nJS> I think my approach differs a little from Junio's (but I haven't\nJS> analysed his deeply) in that the redolog is actually just the slightly\nJS> edited output of git-rev-list --merge-order --parents head base [ the\nJS> edits removes from the list the parallel branches that aren't actually\nJS> involved in the undo ]\n\nJS> Comments?\n\nI've only took a brief glance at your description and found it\nquite sensible.  I did not find anything majorly wrong.\n\nIf you are talking about jit-rewind (I think the message I told\nyou about it was not sent to the list, so the list audience may\nnot know about it, by the way), there is not much to analyze.\n\nIt populates the snapshot pool with the commits in the specified\ncommit chain, and after that it is totally up to the user what\nto do with them, hence there is no redo semantics attached to\nit.  JIT way of doing things is generally more dangerous in that\nit gives you so much more flexibility that it lets you freely\nshoot yourself in the foot ;-).  When the core Plumbing side\nstabilizes I may revisit updating JIT to make certain parts of\nit not so sharp-edged, but I have been busy futzing with the\nPlumbing side lately, and having found not much need to change\nJIT, haven't done much about updating my own Porcelain.\n\n"}]}