{"thread":{"id":"1637","subject":"[RFC] undo and redo","startedAt":"2005-08-24T17:23:39Z","lastAt":"2005-08-25T21:42:08Z","messageCount":21,"participants":["Carl Baldwin","Junio C Hamano","Linus Torvalds","Daniel Barkalow","Kalle Valo","Kirby C. Bohling"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"7709","messageId":"20050824172339.GA7083@hpsvcnb.fc.hp.com","threadId":"1637","inReplyTo":null,"subject":"[RFC] undo and redo","fromName":"Carl Baldwin","fromEmail":"cnb@fc.hp.com","sentAt":"2005-08-24T17:23:39Z","receivedAt":"2005-08-24T17:23:39Z","isPatch":false,"sender":{"key":"cnb@fc.hp.com","avatar":null},"body":"Hello,\n\nSo, one thing that I liked about GNU Arch when I tried it out was the\nability to undo and redo changes in the local working copy.  I decided\nto try to do this with git.  What I have is preliminary.  I'm sure it\ncould use some work.\n\nSo, I started with the assumption that all changes in the working copy\nhave been updated to the cache.  My scripts check this (with\ngit-diff-files) and abort if this is not the case.\n\nUndo calls git-write-tree to write the changes to the object store.  It\nstores that tree's hash and the current HEAD's tree's hash in a file.\nThen it reverts the working copy to HEAD.\n\nRedo grabs these two trees from the file, does git-write-tree to produce\na third tree and merges the three using the old HEAD's tree as the base\nof the merge.  This way, new commits can happen and the local copy can\nbe modified since the undo and it should still work assuming no\nconflicts emerge.\n\nAttached are the two scripts.  Comments and criticism are welcome.\n\nCheers,\nCarl\n\n-- \n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n Carl Baldwin                        Systems VLSI Laboratory\n Hewlett Packard Company\n MS 88                               work: 970 898-1523\n 3404 E. Harmony Rd.                 work: Carl.N.Baldwin@hp.com\n Fort Collins, CO 80525              home: Carl@ecBaldwin.net\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n\n#!/bin/sh\n\n. git-sh-setup-script || die \"Not a git archive\"\n\nif [ -n \"$(git-diff-files)\" ]; then\n    echo The following files should be updated!\n    echo\n    git-diff-files | awk '{print $6}'\nfi\n\nundostack=$GIT_DIR/undostack\n\nif [ ! -s $undostack ]; then\n    echo \"No undo information in $undostack\"\nelse\n    # Read the top of the stack\n    basetree=$(cat $undostack | tail -n 2 | head -n 1)\n    redotree=$(cat $undostack | tail -n 1)\n\n    # Pop the stack\n    cat $undostack | head -n -2 > $undostack.tmp\n    mv $undostack{.tmp,}\n\n    currenttree=$(git-write-tree)\n\n    git-read-tree -u -m $basetree $currenttree $redotree\n    git-merge-cache git-merge-one-file-script -a\nfi\n\n\n#!/bin/sh\n\n. git-sh-setup-script || die \"Not a git archive\"\n\nif [ -n \"$(git-diff-files)\" ]; then\n    echo The following files should be updated!\n    echo\n    git-diff-files | awk '{print $6}'\nfi\n\nundostack=$GIT_DIR/undostack\n\nheadtree=$(git-cat-file commit $(cat $GIT_DIR/HEAD) | head -n 1 | sed -e 's/tree //')\nundotree=$(git-write-tree)\n\nif [ $headtree == $undotree ]; then\n    echo There are no changes to undo.\nelse\n    {\n       echo $headtree\n       echo $undotree\n    } >> $undostack\n\n    echo Saved current state as tree $undotree.\n    echo Reverting to HEAD, $headtree...\n\n    git-checkout-script -f\nfi\n"},{"id":"7710","messageId":"20050824181004.GA18790@hpsvcnb.fc.hp.com","threadId":"1637","inReplyTo":"20050824172339.GA7083@hpsvcnb.fc.hp.com","subject":"Re: [RFC] undo and redo","fromName":"Carl Baldwin","fromEmail":"cnb@fc.hp.com","sentAt":"2005-08-24T18:10:04Z","receivedAt":"2005-08-24T18:10:04Z","isPatch":false,"sender":{"key":"cnb@fc.hp.com","avatar":null},"body":"Oops.  I forgot to actually exit from the script if git-diff-files is\nnon-empty.\n\nAlso, looking at it now, I don't think keeping undo information in a\nstack is the right thing.  But keeping more than just one would be good.\nOh well, my first shot is never perfect.  ;-)\n\nCarl\n\nOn Wed, Aug 24, 2005 at 11:23:39AM -0600, Carl Baldwin wrote:\n> Hello,\n> \n> So, one thing that I liked about GNU Arch when I tried it out was the\n> ability to undo and redo changes in the local working copy.  I decided\n> to try to do this with git.  What I have is preliminary.  I'm sure it\n> could use some work.\n> \n> So, I started with the assumption that all changes in the working copy\n> have been updated to the cache.  My scripts check this (with\n> git-diff-files) and abort if this is not the case.\n> \n> Undo calls git-write-tree to write the changes to the object store.  It\n> stores that tree's hash and the current HEAD's tree's hash in a file.\n> Then it reverts the working copy to HEAD.\n> \n> Redo grabs these two trees from the file, does git-write-tree to produce\n> a third tree and merges the three using the old HEAD's tree as the base\n> of the merge.  This way, new commits can happen and the local copy can\n> be modified since the undo and it should still work assuming no\n> conflicts emerge.\n> \n> Attached are the two scripts.  Comments and criticism are welcome.\n> \n> Cheers,\n> Carl\n> \n> -- \n> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n>  Carl Baldwin                        Systems VLSI Laboratory\n>  Hewlett Packard Company\n>  MS 88                               work: 970 898-1523\n>  3404 E. Harmony Rd.                 work: Carl.N.Baldwin@hp.com\n>  Fort Collins, CO 80525              home: Carl@ecBaldwin.net\n> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n> #!/bin/sh\n> \n> . git-sh-setup-script || die \"Not a git archive\"\n> \n> if [ -n \"$(git-diff-files)\" ]; then\n>     echo The following files should be updated!\n>     echo\n>     git-diff-files | awk '{print $6}'\n> fi\n> \n> undostack=$GIT_DIR/undostack\n> \n> if [ ! -s $undostack ]; then\n>     echo \"No undo information in $undostack\"\n> else\n>     # Read the top of the stack\n>     basetree=$(cat $undostack | tail -n 2 | head -n 1)\n>     redotree=$(cat $undostack | tail -n 1)\n> \n>     # Pop the stack\n>     cat $undostack | head -n -2 > $undostack.tmp\n>     mv $undostack{.tmp,}\n> \n>     currenttree=$(git-write-tree)\n> \n>     git-read-tree -u -m $basetree $currenttree $redotree\n>     git-merge-cache git-merge-one-file-script -a\n> fi\n\n> #!/bin/sh\n> \n> . git-sh-setup-script || die \"Not a git archive\"\n> \n> if [ -n \"$(git-diff-files)\" ]; then\n>     echo The following files should be updated!\n>     echo\n>     git-diff-files | awk '{print $6}'\n> fi\n> \n> undostack=$GIT_DIR/undostack\n> \n> headtree=$(git-cat-file commit $(cat $GIT_DIR/HEAD) | head -n 1 | sed -e 's/tree //')\n> undotree=$(git-write-tree)\n> \n> if [ $headtree == $undotree ]; then\n>     echo There are no changes to undo.\n> else\n>     {\n>        echo $headtree\n>        echo $undotree\n>     } >> $undostack\n> \n>     echo Saved current state as tree $undotree.\n>     echo Reverting to HEAD, $headtree...\n> \n>     git-checkout-script -f\n> fi\n\n\n-- \n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n Carl Baldwin                        Systems VLSI Laboratory\n Hewlett Packard Company\n MS 88                               work: 970 898-1523\n 3404 E. Harmony Rd.                 work: Carl.N.Baldwin@hp.com\n Fort Collins, CO 80525              home: Carl@ecBaldwin.net\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"},{"id":"7711","messageId":"7vu0hfdwql.fsf@assigned-by-dhcp.cox.net","threadId":"1637","inReplyTo":"20050824172339.GA7083@hpsvcnb.fc.hp.com","subject":"Re: [RFC] undo and redo","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-24T18:18:42Z","receivedAt":"2005-08-24T18:18:42Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Carl Baldwin <cnb@fc.hp.com> writes:\n\n> Attached are the two scripts.  Comments and criticism are welcome.\n\nAn obligatory non-technical comment.  I would have liked to see\nthis not in a MIME multipart format, which made commenting on it\na bit harder than necessary.\n\n> Content-Type: text/plain; charset=us-ascii\n> Content-Disposition: attachment; filename=git-undo-script\n>\n> #!/bin/sh\n>\n> . git-sh-setup-script || die \"Not a git archive\"\n>\n> if [ -n \"$(git-diff-files)\" ]; then\n>     echo The following files should be updated!\n>     echo\n>     git-diff-files | awk '{print $6}'\n> fi\n\nThere is nothing wrong with the above, but I would have written\nit like this (I think you forgot to exit after showing the list\nof files):\n\n    git-update-cache --refresh || exit\n\nAlso nice to learn here is \"git-diff-files --name-only\".\n\n> Content-Type: text/plain; charset=us-ascii\n> Content-Disposition: attachment; filename=git-redo-script\n>\n> #!/bin/sh\n>\n> . git-sh-setup-script || die \"Not a git archive\"\n>\n> if [ -n \"$(git-diff-files)\" ]; then\n>     echo The following files should be updated!\n>     echo\n>     git-diff-files | awk '{print $6}'\n> fi\n\nSame here.\n\n>     currenttree=$(git-write-tree)\n>     git-read-tree -u -m $basetree $currenttree $redotree\n>     git-merge-cache git-merge-one-file-script -a\n\nInteresting.  Very interesting.\n"},{"id":"7717","messageId":"Pine.LNX.4.58.0508241148480.3317@g5.osdl.org","threadId":"1637","inReplyTo":"20050824181004.GA18790@hpsvcnb.fc.hp.com","subject":"Re: [RFC] undo and redo","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-08-24T18:51:32Z","receivedAt":"2005-08-24T18:51:32Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Wed, 24 Aug 2005, Carl Baldwin wrote:\n>\n> Oops.  I forgot to actually exit from the script if git-diff-files is\n> non-empty.\n> \n> Also, looking at it now, I don't think keeping undo information in a\n> stack is the right thing.  But keeping more than just one would be good.\n> Oh well, my first shot is never perfect.  ;-)\n\nI would actually argue that\n\n\tgit checkout -b newbranch <undo-point>\n\nis the perfect undo.\n\nIt leaves the old state in the old branch, and creates a new branch (and\nchecks it out) with the state you want to revert to. The advantage is\nexactly that there is no \"stack\" of undo's: you can have multiple\nindependent undo's pending, and you can continue development at any of \nthem. And merge the results together.\n\nOf course, right now we don't have a \"delete branch\" command, but it's \nreally as simple as\n\n\trm .git/refs/heads/branchname\n\n(and eventually you may want to do a \"git prune\" to get rid of stale\nobjects, but that's a separate issue).\n\n\t\tLinus\n"},{"id":"7721","messageId":"20050824195615.GA693@hpsvcnb.fc.hp.com","threadId":"1637","inReplyTo":"Pine.LNX.4.58.0508241148480.3317@g5.osdl.org","subject":"Re: [RFC] undo and redo","fromName":"Carl Baldwin","fromEmail":"cnb@fc.hp.com","sentAt":"2005-08-24T19:56:15Z","receivedAt":"2005-08-24T19:56:15Z","isPatch":false,"sender":{"key":"cnb@fc.hp.com","avatar":null},"body":"On Wed, Aug 24, 2005 at 11:51:32AM -0700, Linus Torvalds wrote:\n> \n> \n> On Wed, 24 Aug 2005, Carl Baldwin wrote:\n> >\n> > Oops.  I forgot to actually exit from the script if git-diff-files is\n> > non-empty.\n> > \n> > Also, looking at it now, I don't think keeping undo information in a\n> > stack is the right thing.  But keeping more than just one would be good.\n> > Oh well, my first shot is never perfect.  ;-)\n> \n> I would actually argue that\n> \n> \tgit checkout -b newbranch <undo-point>\n> \n> is the perfect undo.\n\nYes, this does the job nicely.  I've used it like this effectively.  I\nmeant for undo/redo to be a lighter weight way of moving (uncommitted)\nchanges out of the way briefly and then replaying them onto the working\ndirectory later.\n\n> It leaves the old state in the old branch, and creates a new branch (and\n> checks it out) with the state you want to revert to. The advantage is\n> exactly that there is no \"stack\" of undo's: you can have multiple\n> independent undo's pending, and you can continue development at any of \n> them. And merge the results together.\n\nThe \"stack\" was the wrong thing to do.  I think I would have undo pick a\nname like undo-1, undo-2 etc.  Or something like that.  redo would pick\nthe most recent unless told to do otherwise.\n\nA possible advantage of undo is having the freedom to stay on the\ncurrent branch or switch to another.\n\n> Of course, right now we don't have a \"delete branch\" command, but it's \n> really as simple as\n>\n> \trm .git/refs/heads/branchname\n> \n> (and eventually you may want to do a \"git prune\" to get rid of stale\n> objects, but that's a separate issue).\n> \n> \t\tLinus\n> \n\nThis brings up a good point (indirectly).  \"git prune\" would destroy the\nundo objects.  I had thought of this but decided to ignore it for the\ntime being.\n\nCarl\n\n-- \n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n Carl Baldwin                        Systems VLSI Laboratory\n Hewlett Packard Company\n MS 88                               work: 970 898-1523\n 3404 E. Harmony Rd.                 work: Carl.N.Baldwin@hp.com\n Fort Collins, CO 80525              home: Carl@ecBaldwin.net\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"},{"id":"7722","messageId":"20050824200134.GB693@hpsvcnb.fc.hp.com","threadId":"1637","inReplyTo":"7vu0hfdwql.fsf@assigned-by-dhcp.cox.net","subject":"Re: [RFC] undo and redo","fromName":"Carl Baldwin","fromEmail":"cnb@fc.hp.com","sentAt":"2005-08-24T20:01:34Z","receivedAt":"2005-08-24T20:01:34Z","isPatch":false,"sender":{"key":"cnb@fc.hp.com","avatar":null},"body":"On Wed, Aug 24, 2005 at 11:18:42AM -0700, Junio C Hamano wrote:\n> Carl Baldwin <cnb@fc.hp.com> writes:\n> \n> > Attached are the two scripts.  Comments and criticism are welcome.\n> \n> An obligatory non-technical comment.  I would have liked to see\n> this not in a MIME multipart format, which made commenting on it\n> a bit harder than necessary.\n> \n> > Content-Type: text/plain; charset=us-ascii\n> > Content-Disposition: attachment; filename=git-undo-script\n> >\n> > #!/bin/sh\n> >\n> > . git-sh-setup-script || die \"Not a git archive\"\n> >\n> > if [ -n \"$(git-diff-files)\" ]; then\n> >     echo The following files should be updated!\n> >     echo\n> >     git-diff-files | awk '{print $6}'\n> > fi\n> \n> There is nothing wrong with the above, but I would have written\n> it like this (I think you forgot to exit after showing the list\n> of files):\n> \n>     git-update-cache --refresh || exit\n\nI'll take this.  This is what I was going for but being new to git I\ndidn't know all that was available.  A good reason to request comments\n:-)\n\n> Also nice to learn here is \"git-diff-files --name-only\".\n\nAlso good to know, thanks.\n\nCarl\n\n-- \n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n Carl Baldwin                        Systems VLSI Laboratory\n Hewlett Packard Company\n MS 88                               work: 970 898-1523\n 3404 E. Harmony Rd.                 work: Carl.N.Baldwin@hp.com\n Fort Collins, CO 80525              home: Carl@ecBaldwin.net\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"},{"id":"7724","messageId":"Pine.LNX.4.63.0508241634350.23242@iabervon.org","threadId":"1637","inReplyTo":"20050824195615.GA693@hpsvcnb.fc.hp.com","subject":"Re: [RFC] undo and redo","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-08-24T20:44:48Z","receivedAt":"2005-08-24T20:44:48Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Wed, 24 Aug 2005, Carl Baldwin wrote:\n\n> This brings up a good point (indirectly).  \"git prune\" would destroy the\n> undo objects.  I had thought of this but decided to ignore it for the\n> time being.\n\nIf you made undo store the tree under refs somewhere, git prune would\npreserve it.\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"7725","messageId":"20050824204736.GA13194@hpsvcnb.fc.hp.com","threadId":"1637","inReplyTo":"Pine.LNX.4.63.0508241634350.23242@iabervon.org","subject":"Re: [RFC] undo and redo","fromName":"Carl Baldwin","fromEmail":"cnb@fc.hp.com","sentAt":"2005-08-24T20:47:36Z","receivedAt":"2005-08-24T20:47:36Z","isPatch":false,"sender":{"key":"cnb@fc.hp.com","avatar":null},"body":"This is interesting.  Can a ref be to a tree rather than a commit?  And\nit still works?  I guess it would.  I hadn't thought about that.\n\nWill prune preserve any tree mentioned in any file in refs?  How does\nthis work exactly?\n\nCheers,\nCarl\n\nOn Wed, Aug 24, 2005 at 04:44:48PM -0400, Daniel Barkalow wrote:\n> On Wed, 24 Aug 2005, Carl Baldwin wrote:\n> \n> > This brings up a good point (indirectly).  \"git prune\" would destroy the\n> > undo objects.  I had thought of this but decided to ignore it for the\n> > time being.\n> \n> If you made undo store the tree under refs somewhere, git prune would\n> preserve it.\n> \n> \t-Daniel\n> *This .sig left intentionally blank*\n> \n\n-- \n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n Carl Baldwin                        Systems VLSI Laboratory\n Hewlett Packard Company\n MS 88                               work: 970 898-1523\n 3404 E. Harmony Rd.                 work: Carl.N.Baldwin@hp.com\n Fort Collins, CO 80525              home: Carl@ecBaldwin.net\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"},{"id":"7726","messageId":"Pine.LNX.4.63.0508241651420.23242@iabervon.org","threadId":"1637","inReplyTo":"20050824204736.GA13194@hpsvcnb.fc.hp.com","subject":"Re: [RFC] undo and redo","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-08-24T21:04:51Z","receivedAt":"2005-08-24T21:04:51Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Wed, 24 Aug 2005, Carl Baldwin wrote:\n\n> This is interesting.  Can a ref be to a tree rather than a commit?  And\n> it still works?  I guess it would.  I hadn't thought about that.\n\nGenerally, each subdirectory of refs/ has refs to objects of the same\ntype, and heads/ is commits, but other directories are other things. tags/\nis all tag objects, and you could have undo/ be trees.\n\n> Will prune preserve any tree mentioned in any file in refs?  How does\n> this work exactly?\n\nIt keeps any object reachable from an object that there's a ref to in\nrefs.\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"7731","messageId":"7vd5o3ar4a.fsf@assigned-by-dhcp.cox.net","threadId":"1637","inReplyTo":"Pine.LNX.4.63.0508241651420.23242@iabervon.org","subject":"Re: [RFC] undo and redo","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-24T22:48:21Z","receivedAt":"2005-08-24T22:48:21Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Daniel Barkalow <barkalow@iabervon.org> writes:\n\n> Generally, each subdirectory of refs/ has refs to objects of the same\n> type, and heads/ is commits, but other directories are other things. tags/\n> is all tag objects, and you could have undo/ be trees.\n\nThat's OK from the prune front, but I am not sure what the\nramifications of this for pulling, pushing, and resolving.\nI would not recommend it without really thinking it through.\n\nAlso note that tags/ is not all tag objects.  I think \"git tag\"\nby default creates a lightweight tag, not an annotated kind.\n\nI think you could do either one of two things.  As usual, totally\nuntested.  Just thinking aloud.\n\n(1) A hack.\n\n     - Have a single \"undo-redo\" branch, which was forked from\n       somewhere on the \"master\" branch.\n\n     - When doing \"undo\", make a commit that has the current top\n       of undo-redo branch as the first parent and the current\n       HEAD commit as the second parent, using the tree that\n       represents your snapshot, to grow \"undo-redo\" branch.\n\n       No, this commit does *not* represent a merge, but I am\n       abusing the capability to record more than one parent\n       commits.\n\n     - When running \"redo\", you would want a handy way to name\n       what to redo.  You can say \"undo-redo~N\" to mean \"Nth\n       from the top of undo-redo branch.\n\n       Your implementation of \"redo\" can either be (patch way):\n\n       git-diff-tree -p undo-redo~N^ undo-redo~N | git apply --index\n\n       or (merge way):\n\n       git-read-tree -m undo-redo~N^2 undo-redo~N HEAD &&\n       git-merge-cache -o git-merge-one-file-script -a\n\n(2) Try StGIT.\n"},{"id":"7734","messageId":"20050825024134.GA31886@hpsvcnb.fc.hp.com","threadId":"1637","inReplyTo":"7vd5o3ar4a.fsf@assigned-by-dhcp.cox.net","subject":"Re: [RFC] undo and redo","fromName":"Carl Baldwin","fromEmail":"cnb@fc.hp.com","sentAt":"2005-08-25T02:41:34Z","receivedAt":"2005-08-25T02:41:34Z","isPatch":false,"sender":{"key":"cnb@fc.hp.com","avatar":null},"body":"Well, both are good ideas.  Both are stack oriented, though.\n\nI see what you mean about adding an undo directory to .git/refs/.  I\nwill do some tests... (read further)\n\nOn Wed, Aug 24, 2005 at 03:48:21PM -0700, Junio C Hamano wrote:\n> Daniel Barkalow <barkalow@iabervon.org> writes:\n> \n> > Generally, each subdirectory of refs/ has refs to objects of the same\n> > type, and heads/ is commits, but other directories are other things. tags/\n> > is all tag objects, and you could have undo/ be trees.\n> \n> That's OK from the prune front, but I am not sure what the\n> ramifications of this for pulling, pushing, and resolving.\n> I would not recommend it without really thinking it through.\n\nSo, I've tried cloning, pulling to|from, pushing to|from and resolving\nmerges in a repository with undo information stored under\n.git/refs/undo.  None of these operations seem to notice the existence\nof this directory.  I think this is good.\n\nThe cloned repository does not end up 'inheriting' the undo directory\n(as I would expect) but does end up with any objects reachable from the\nundo tree.  However, these objects get pruned on the next 'git prune'.\nThis, I think, is minor.\n\nPull seems to ignore the undo directory and, of course, the objects\nreachable by the undo trees.  This is what I expected and wanted.\n\nResolving merges worked as expected.\n\nI think undo trees should be considered local to the repository and this\nis the behavior that I observed.  I think this is a positive.\n\nBefore reading your message, I polished up the scripts and changed them\nso that they store the undo tree and the base tree's hashes in the\n.git/refs/undo directory.  Also, git-redo-script can take an optional\nargument...the name of the undo to replay.  I guess undo should also\ntake an optional argument to give the undo tree some symbolic name.\n\nI think this is getting rather solid.  Let me know what you think.\n\nHere is the git-undo-script:\n\n#!/bin/sh\n\n. git-sh-setup-script || die \"Not a git archive\"\n\ngit-update-cache --refresh || exit 1\n\nundodir=$GIT_DIR/refs/undo\n\nundoinfo=$undodir/$(date +%Y.%m.%d.%H.%M.%S)\n\nheadtree=$(git-cat-file commit $(cat $GIT_DIR/HEAD) | sed -n 's/^tree //p')\nundotree=$(git-write-tree)\n\nif [ $headtree == $undotree ]; then\n    echo There are no changes to undo.\nelse\n    mkdir -p $(dirname $undoinfo)\n    echo $headtree > $undoinfo.base\n    echo $undotree > $undoinfo.undo\n\n    echo Saved current state in $undodir as $(basename $undoinfo)\n\n    git-read-tree -m -u $undotree $headtree\nfi\n\n# --- SNIP ---\n\nand here, is the redo script\n\n#!/bin/sh\n\n. git-sh-setup-script || die \"Not a git archive\"\n\ngit-update-cache --refresh || exit 1\n\nusage () {\n    echo >&2 \"Usage: git-redo-script [undo name]\"\n    exit 1\n}\n\nundodir=$GIT_DIR/refs/undo\n\n# If an 'undo name' was given on the command line then try to use it.\n# If not, then automatically pick the most recent undo.\nundoinfo=\ncase \"$#\" in\n0)\n    undoinfo=$undodir/$(ls -tr $undodir | sed -n 's/\\.undo$//p' | tail -n 1)\n    ;;\n1)\n    if [ -s $undodir/$1 ]; then\n        undoinfo=$(echo $undodir/$1 | sed -n \"s/\\.[^.]*$//p\")\n    elif [ -s $undodir/$1.undo -a -s $undodir/$1.base ]; then\n        undoinfo=$undodir/$1\n    else\n        usage\n    fi\n    ;;\n*)\n    usage\n    ;;\nesac\n\n# Perform a three-way merge between the base tree, undo tree and current index\nif [ ! -s $undoinfo.undo -o ! -s $undoinfo.base ]; then\n    echo \"No undo information available\"\nelse\n    git-read-tree -u -m $(cat $undoinfo.base) $(cat $undoinfo.undo) $(git-write-tree)\n    git-merge-cache git-merge-one-file-script -a\n\n    rm -f $undoinfo.*\n    test -z \"$(ls $undodir)\" && rmdir $undodir\nfi\n\n# --- SNIP ---\n\nI would be glad to write up documentation and provide a patch.\n\nCheers,\nCarl\n\n> Also note that tags/ is not all tag objects.  I think \"git tag\"\n> by default creates a lightweight tag, not an annotated kind.\n> \n> I think you could do either one of two things.  As usual, totally\n> untested.  Just thinking aloud.\n> \n> (1) A hack.\n> \n>      - Have a single \"undo-redo\" branch, which was forked from\n>        somewhere on the \"master\" branch.\n> \n>      - When doing \"undo\", make a commit that has the current top\n>        of undo-redo branch as the first parent and the current\n>        HEAD commit as the second parent, using the tree that\n>        represents your snapshot, to grow \"undo-redo\" branch.\n> \n>        No, this commit does *not* represent a merge, but I am\n>        abusing the capability to record more than one parent\n>        commits.\n> \n>      - When running \"redo\", you would want a handy way to name\n>        what to redo.  You can say \"undo-redo~N\" to mean \"Nth\n>        from the top of undo-redo branch.\n> \n>        Your implementation of \"redo\" can either be (patch way):\n> \n>        git-diff-tree -p undo-redo~N^ undo-redo~N | git apply --index\n> \n>        or (merge way):\n> \n>        git-read-tree -m undo-redo~N^2 undo-redo~N HEAD &&\n>        git-merge-cache -o git-merge-one-file-script -a\n> \n> (2) Try StGIT.\n> \n> \n\n-- \n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n Carl Baldwin                        Systems VLSI Laboratory\n Hewlett Packard Company\n MS 88                               work: 970 898-1523\n 3404 E. Harmony Rd.                 work: Carl.N.Baldwin@hp.com\n Fort Collins, CO 80525              home: Carl@ecBaldwin.net\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"},{"id":"7740","messageId":"7v1x4izjtm.fsf@assigned-by-dhcp.cox.net","threadId":"1637","inReplyTo":"20050825024134.GA31886@hpsvcnb.fc.hp.com","subject":"Re: [RFC] undo and redo","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-25T05:06:45Z","receivedAt":"2005-08-25T05:06:45Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"> So, I've tried cloning, pulling to|from, pushing to|from and resolving\n> merges in a repository with undo information stored under\n> .git/refs/undo.  None of these operations seem to notice the existence\n> of this directory.  I think this is good.\n\nWhat I meant was that, when \"undo/bar\" is a tree object, things\nmay work in a funny way:\n\n    $ git pull ../repo-with-undo/.git refs/undo/bar\n\n    $ git push ../other-repo/.git undo/bar:refs/heads/foo\n    $ cd ../other-repo && git resolve master foo 'Attempt to merge undo'\n\nI think this undo/redo first needs to be thought about how best\nit is used.  My guess is that the workflow you have in mind is\nsomething like this:\n\n    $ git checkout master\n    $ hack hack hack\n    # Hmph, it almost works, and but my boss says work on\n    # some other feature that is more urgent\n    $ git undo\n    Saved current state as 2005-08-24T20:32:22\n    $ work work work\n    $ git commit -m 'Boring but urgent fix'\n    # Ok, now let's back to the thing I wanted to do.\n    $ git redo\n    # I happen to know it is the last undo, so I did not name\n    # it, but I could have said 2005-08-24T20:32:22\n    $ hack more\n    $ git commit -m 'Finally fix frotz.'\n\nI see some problems in this.\n\nOne is minor.  As you mentioned about \"giving undo a symbolic\nname\", after you accumulate a handful undo, you would need them\nto have descriptive names, and a way to list them before using\n\"git redo\".\n\nBut as Linus suggested in another reply, you could as well have\ndone this without inventing these two commands.\n\n    $ git checkout master\n    $ hack hack hack\n    # Hmph, it almost works, and but my boss says work on\n    # some other feature that is more urgent\n    $ git commit -m 'WIP - fix frotz'\n    $ git branch anchor-frotz\n    $ git reset --hard master^\n    $ work work work\n    $ git commit -m 'Boring but urgent fix'\n    # Ok, now let's go back to the thing I wanted to do.\n    $ git pull . anchor-frotz\n    $ rm .git/heads/anchor-frotz\n    $ git reset --soft master^\n    $ hack more\n    $ git commit -m 'Finally fix frotz.'\n\nThe above flow would be something somebody not so organized\n(like myself) would do.  A perfect person would have done this:\n\n    $ git checkout -b frotz master\n    $ hack hack hack\n    # Hmph, it almost works, and but my boss says work on\n    # some other feature that is more urgent\n    $ git commit -m 'WIP - fix frotz'\n    $ git checkout master\n    $ work work work\n    $ git commit -m 'Boring but urgent fix'\n    # Ok, now let's go back to the thing I wanted to do.\n    $ git checkout frotz\n    $ git reset --soft HEAD^\n    $ hack more\n    $ git commit -m 'Finally fix frotz.'\n    $ git checkout master\n    $ git pull . frotz\n    $ rm .git/refs/heads/frotz\n\nThe \"perfect person\" approach has an added benefit that you\ncould have made intermediate commits while doing \"hacking\",\nbecause your hackery is always done in the \"frotz\" branch.\n\nOf course, the scenarios your undo/redo is useful for may not be\nlimited to this \"handling interrupt\" use case.  If that is the\nonly thing it solves, then I do not see much point having them\nas new commands.  I think the undo/redo has potential beyond\nthat.\n\nSo let's first clarify what kind of workflow these new commands\nwould help, how well that workflow is applicable in general, and\nthen how well these new commands would help that workflow.\n\n> I would be glad to write up documentation and provide a patch.\n\nSure.  I think a set of patches for new commands, and new\noptions to existing commands should ideally include the\nfollowing:\n\n - Justification, such as:\n\n   - The problems new commands/options address.\n   - The expected workflow the new commands/options fit in.\n   - How useful that workflow is.\n   - How impossible or cumbersome to achieve that workflow using\n     existing tools.\n\n   Some of these should go to the commit log message, and the\n   documentation to describe the \"best practice\" workflow using\n   the new feature should go to Documentation/howto/ directory.\n\n - Documentation.  Files Documentation/git-*.txt to describe\n   new commands or updates to existing pages, new entry in\n   Documentation/Makefile as necessary, and a new link from\n   Documentation/git.txt to reach that page.\n\n - Implementation.\n\n - Test scripts in t/ directory, either a new test script or\n   updates to existing ones, if the patch is to fix existing\n   implementation.\n"},{"id":"7748","messageId":"20050825163201.GA3944@hpsvcnb.fc.hp.com","threadId":"1637","inReplyTo":"7v1x4izjtm.fsf@assigned-by-dhcp.cox.net","subject":"Re: [RFC] undo and redo","fromName":"Carl Baldwin","fromEmail":"cnb@fc.hp.com","sentAt":"2005-08-25T16:32:01Z","receivedAt":"2005-08-25T16:32:01Z","isPatch":false,"sender":{"key":"cnb@fc.hp.com","avatar":null},"body":"On Wed, Aug 24, 2005 at 10:06:45PM -0700, Junio C Hamano wrote:\n> > So, I've tried cloning, pulling to|from, pushing to|from and resolving\n> > merges in a repository with undo information stored under\n> > .git/refs/undo.  None of these operations seem to notice the existence\n> > of this directory.  I think this is good.\n> \n> What I meant was that, when \"undo/bar\" is a tree object, things\n> may work in a funny way:\n> \n>     $ git pull ../repo-with-undo/.git refs/undo/bar\n> \n>     $ git push ../other-repo/.git undo/bar:refs/heads/foo\n>     $ cd ../other-repo && git resolve master foo 'Attempt to merge undo'\n\nI was thinking that undo trees should not be pushed and pulled between\nrepositories.  For this I would use a new branch with proper commits as\nLinus suggested.\n\n> I think this undo/redo first needs to be thought about how best\n> it is used.  My guess is that the workflow you have in mind is\n> something like this:\n> \n>     $ git checkout master\n>     $ hack hack hack\n>     # Hmph, it almost works, and but my boss says work on\n>     # some other feature that is more urgent\n>     $ git undo\n>     Saved current state as 2005-08-24T20:32:22\n>     $ work work work\n>     $ git commit -m 'Boring but urgent fix'\n>     # Ok, now let's back to the thing I wanted to do.\n>     $ git redo\n>     # I happen to know it is the last undo, so I did not name\n>     # it, but I could have said 2005-08-24T20:32:22\n>     $ hack more\n>     $ git commit -m 'Finally fix frotz.'\n\nFor this, I may also use branching, as suggested.  I meant for undo/redo\nto be a lighter weight alternative to allow for a faster context switch.\nI am reluctant to commit what I have in my working directory unless I\nhave taken the time to review the changes using diff tools and cleaned\nup considerably.  This is my way of being a careful developer.  Not all\ndevelopers share my style but I know many that do.  This makes\ncommitting a heavy weight operation for me.\n\nSo, referring to your example.  If my 'boss' says that I need to switch\nto working on 'Boring but urgent fix' for the next *week* or more I will\nlikely take the time to make the full context switch to a new branch and\nwork on the fix.  I may also choose to just clone my repository and use\na new working directory.  If the fix takes just a day or two I may do\nthe same.\n\nNow, let's say that the 'fix' is something that I can do in an hour or\ntwo and quickly get back to where I was.  In this context, making the\nfull context switch can feel very cumbersome compared to the amount of\nwork required to make the fix.  Now, a simple 'git undo' will ease this\nswitch.\n\nAnother example is if I'm working on a commit and suddenly get a\nbrilliant idea for some easy modification that I want to make and commit\nby itself before making this commit.  I can do this easily with\n\n        % git undo\n        % carefully make easy change\n        % git commit\n        % git redo\n\nHaving a light-weight alternative like this could make the difference\nbetween realizing the easy, brilliant idea and forgetting about it on\nthe back burner because it was just too cumbersome to make the context\nswitch.\n\nThe bottom line is that I don't argue against using the existing\nwork-flows.  I hope to add the flexibility to use various work-flows to\nfit the job at hand.\n\n[ stuff deleted ]\n\n>     $ git checkout master\n>     $ hack hack hack\n>     # Hmph, it almost works, and but my boss says work on\n>     # some other feature that is more urgent\n>     $ git commit -m 'WIP - fix frotz'\n>     $ git branch anchor-frotz\n>     $ git reset --hard master^\n>     $ work work work\n>     $ git commit -m 'Boring but urgent fix'\n>     # Ok, now let's go back to the thing I wanted to do.\n>     $ git pull . anchor-frotz\n>     $ rm .git/heads/anchor-frotz\n>     $ git reset --soft master^\n>     $ hack more\n>     $ git commit -m 'Finally fix frotz.'\n\nAgain, these are effective.  I simply want to provide an alternative\nlight weight way of accomplishing this.\n\n> The above flow would be something somebody not so organized\n> (like myself) would do.  A perfect person would have done this:\n> \n>     $ git checkout -b frotz master\n>     $ hack hack hack\n>     # Hmph, it almost works, and but my boss says work on\n>     # some other feature that is more urgent\n>     $ git commit -m 'WIP - fix frotz'\n>     $ git checkout master\n>     $ work work work\n>     $ git commit -m 'Boring but urgent fix'\n>     # Ok, now let's go back to the thing I wanted to do.\n>     $ git checkout frotz\n>     $ git reset --soft HEAD^\n>     $ hack more\n>     $ git commit -m 'Finally fix frotz.'\n>     $ git checkout master\n>     $ git pull . frotz\n>     $ rm .git/refs/heads/frotz\n> \n> The \"perfect person\" approach has an added benefit that you\n> could have made intermediate commits while doing \"hacking\",\n> because your hackery is always done in the \"frotz\" branch.\n> \n> Of course, the scenarios your undo/redo is useful for may not be\n> limited to this \"handling interrupt\" use case.  If that is the\n> only thing it solves, then I do not see much point having them\n> as new commands.  I think the undo/redo has potential beyond\n> that.\n\nWhat other potential do you see?  I sounds like you had a stream of\nthought here that didn't make it in the email.  I think there are\nprobably many ways that it can be useful.  I'll ask some of my\ncolleagues here who have liked undo/redo type functionality what they\nthink.\n\nI think it would be impossible to think of all of the possibilities\nahead of time.  But, if you've thought of some, please share :-)\n\n> So let's first clarify what kind of workflow these new commands\n> would help, how well that workflow is applicable in general, and\n> then how well these new commands would help that workflow.\n> \n> > I would be glad to write up documentation and provide a patch.\n> \n> Sure.  I think a set of patches for new commands, and new\n> options to existing commands should ideally include the\n> following:\n> \n>  - Justification, such as:\n> \n>    - The problems new commands/options address.\n>    - The expected workflow the new commands/options fit in.\n>    - How useful that workflow is.\n>    - How impossible or cumbersome to achieve that workflow using\n>      existing tools.\n> \n>    Some of these should go to the commit log message, and the\n>    documentation to describe the \"best practice\" workflow using\n>    the new feature should go to Documentation/howto/ directory.\n> \n>  - Documentation.  Files Documentation/git-*.txt to describe\n>    new commands or updates to existing pages, new entry in\n>    Documentation/Makefile as necessary, and a new link from\n>    Documentation/git.txt to reach that page.\n> \n>  - Implementation.\n> \n>  - Test scripts in t/ directory, either a new test script or\n>    updates to existing ones, if the patch is to fix existing\n>    implementation.\n\nThis all sounds reasonable.  I'm willing to do this work.\n\nCheers,\nCarl\n\n-- \n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n Carl Baldwin                        Systems VLSI Laboratory\n Hewlett Packard Company\n MS 88                               work: 970 898-1523\n 3404 E. Harmony Rd.                 work: Carl.N.Baldwin@hp.com\n Fort Collins, CO 80525              home: Carl@ecBaldwin.net\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"},{"id":"7749","messageId":"87u0hdor0m.fsf@litku.valo.iki.fi","threadId":"1637","inReplyTo":"20050825163201.GA3944@hpsvcnb.fc.hp.com","subject":"Re: [RFC] undo and redo","fromName":"Kalle Valo","fromEmail":"kalle.valo@iki.fi","sentAt":"2005-08-25T17:39:05Z","receivedAt":"2005-08-25T17:39:05Z","isPatch":false,"sender":{"key":"kalle.valo@iki.fi","avatar":null},"body":"Carl Baldwin <cnb@fc.hp.com> writes:\n\n> For this, I may also use branching, as suggested.  I meant for undo/redo\n> to be a lighter weight alternative to allow for a faster context switch.\n\nI have been missing the undo command since I started to use git, so\nI'll share a user's perspective. \n\nI was also considering undo as a really lightweight command, nothing\ntoo fancy. Usually, I want to try implement something wild or stupid,\nbut almost immediately decide to abandon it. With 'git undo', this\nkind of prototyping would be really easy. For me, redo would be just a\nbackup if (read: when) I undo something important, nothing more. For\nanything else I would use branches, as was suggested.\n\n-- \nKalle Valo\n"},{"id":"7754","messageId":"20050825195918.GD7461@birddog.com","threadId":"1637","inReplyTo":"20050825163201.GA3944@hpsvcnb.fc.hp.com","subject":"Re: [RFC] undo and redo","fromName":"Kirby C. Bohling","fromEmail":"kbohling@birddog.com","sentAt":"2005-08-25T19:59:18Z","receivedAt":"2005-08-25T19:59:18Z","isPatch":false,"sender":{"key":"kbohling@birddog.com","avatar":null},"body":"On Thu, Aug 25, 2005 at 10:32:01AM -0600, Carl Baldwin wrote:\n<snip...>\n> Another example is if I'm working on a commit and suddenly get a\n> brilliant idea for some easy modification that I want to make and commit\n> by itself before making this commit.  I can do this easily with\n> \n>         % git undo\n>         % carefully make easy change\n>         % git commit\n>         % git redo\n> \n> Having a light-weight alternative like this could make the difference\n> between realizing the easy, brilliant idea and forgetting about it on\n> the back burner because it was just too cumbersome to make the context\n> switch.\n> \n> The bottom line is that I don't argue against using the existing\n> work-flows.  I hope to add the flexibility to use various work-flows to\n> fit the job at hand.\n> \n<snip...>\n\n[Not much of a git user, but am evaluating it for possible future\nusage]... \n\nWhy not just save the changes to a file via a patch.  Just like you\nwould if you were sending a patch to someone else.  I have the work\nflow you are talking about when I use CVS.  I just create a patch,\napply the patch in reverse (or run the command to get you a clean\nworking tree in the SCM).  Make my unrelated changes commit it.\nThen apply the patch, possibly resolve merge conflicts,  and proceed\nwith finishing my original work.\n\nAssuming your patch creation and application tools capture all the\nmeta-data the SCM has (which I believe git does), it's pretty simple\nto simulate what you want manaully.  With only a handful of\ncommands.\n\nI see the appeal of not having manually deal with the files, but\nassuming you don't feel it's branch worthy, and you don't want to\nhave it be something someone else can access externally, it doesn't\nseem like a feature I can't get almost as simply with existing git\ncommands.  \n\nI guess my final question is what does undo/redo have over saving\nstuff away in a patch assuming that the patch captures all of the\nSCM meta-data (the add/move/remove file type commands).  If git\ndoesn't capture all the meta-data in a patch, it would seem better\nto make it do that and get this as a side-affect.\n\n    Thanks,\n        Kirby\n"},{"id":"7755","messageId":"7vmzn5vkg6.fsf@assigned-by-dhcp.cox.net","threadId":"1637","inReplyTo":"20050825195918.GD7461@birddog.com","subject":"Re: [RFC] undo and redo","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-25T20:19:05Z","receivedAt":"2005-08-25T20:19:05Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Kirby C. Bohling\" <kbohling@birddog.com> writes:\n\n> I guess my final question is what does undo/redo have over saving\n> stuff away in a patch assuming that the patch captures all of the\n> SCM meta-data (the add/move/remove file type commands).  If git\n> doesn't capture all the meta-data in a patch, it would seem better\n> to make it do that and get this as a side-affect.\n\nOne thing that Carl's undo saves that is not easily available in\nthe patch form is the \"what is this patch based on\" information.\nIf you had it, you could do a three-way merge instead of patch\napplication.\n\nYou were at A (time flows from left to right) when somebody\n(maybe your bright idea) interrupted you.  You take a snapshot\nof your tree state D as a pair <A, D>, and rewind the tree to\noriginal commit A's state:\n\n -->A\n     \\\n      D\n\nThen you do the work that interrupted you, maybe making commits\nB and then C:\n\n -->A-->B-->C\n     \\\n      D\n\nAt this point, you would want to restart working on whatever you\nwere doing, which is the difference between A->D applied on top\nof C.\n\nYou could keep that information as a patch between A->D and\napply it on top of C to get there, which is your approach if I\nam reading you correctly.  Carl does a three-way merge between C\nand D using A as the pivot point.\n"},{"id":"7757","messageId":"20050825203733.GA26539@hpsvcnb.fc.hp.com","threadId":"1637","inReplyTo":"20050825195918.GD7461@birddog.com","subject":"Re: [RFC] undo and redo","fromName":"Carl Baldwin","fromEmail":"cnb@fc.hp.com","sentAt":"2005-08-25T20:37:33Z","receivedAt":"2005-08-25T20:37:33Z","isPatch":false,"sender":{"key":"cnb@fc.hp.com","avatar":null},"body":"On Thu, Aug 25, 2005 at 02:59:18PM -0500, Kirby C. Bohling wrote:\n> On Thu, Aug 25, 2005 at 10:32:01AM -0600, Carl Baldwin wrote:\n> <snip...>\n> > Another example is if I'm working on a commit and suddenly get a\n> > brilliant idea for some easy modification that I want to make and commit\n> > by itself before making this commit.  I can do this easily with\n> > \n> >         % git undo\n> >         % carefully make easy change\n> >         % git commit\n> >         % git redo\n> > \n> > Having a light-weight alternative like this could make the difference\n> > between realizing the easy, brilliant idea and forgetting about it on\n> > the back burner because it was just too cumbersome to make the context\n> > switch.\n> > \n> > The bottom line is that I don't argue against using the existing\n> > work-flows.  I hope to add the flexibility to use various work-flows to\n> > fit the job at hand.\n> > \n> <snip...>\n> \n> [Not much of a git user, but am evaluating it for possible future\n> usage]... \n> \n> Why not just save the changes to a file via a patch.  Just like you\n> would if you were sending a patch to someone else.  I have the work\n> flow you are talking about when I use CVS.  I just create a patch,\n> apply the patch in reverse (or run the command to get you a clean\n> working tree in the SCM).  Make my unrelated changes commit it.\n> Then apply the patch, possibly resolve merge conflicts,  and proceed\n> with finishing my original work.\n\nI used to do this with CVS too.  For you and me, people who are patch\nsavy veterans, this is great!  However, as easy as it is I knew very few\nother developers who even thought about doing it.  In the real world,\nmany people see a huge difference between:\n\ngit diff-cache > $patchfile\ncat $patchfile | patch -R -p1\ndo work\ncat $patchfile | patch -p1\n\nAND\n\ngit undo\ndo work\ngit redo\n\nThe first one simply never happens with most developers.  Most don't\nreally think of doing something outside the tool.  The second option\nwill likely get used.  Plus, I know at least one person here who is very\ngood with patches and working outside the tool and still would love to\nhave the second approach available.\n\nIs there something wrong with having flexibility?  It seems most of the\ncriticism of this feature is that there is already a way to accomplish\nwhat I want to do.  Tools that can't be used flexibly are not tools that\nI like to use.  Heck, I'm on UNIX aren't I?\n\nOops, sorry for the rant.  I'm really not in a bad mood... really.  I\nhope it didn't sound like that :-).  Oh, and I didn't mean to suggest\nthat git is not flexible in other regards.  I think its great!  Moving\nalong...\n\n> Assuming your patch creation and application tools capture all the\n> meta-data the SCM has (which I believe git does), it's pretty simple\n> to simulate what you want manaully.  With only a handful of\n> commands.\n\nI can simulate git manually too with just a few more commands.  Where's\nthe cutoff?\n\n> I see the appeal of not having manually deal with the files, but\n> assuming you don't feel it's branch worthy, and you don't want to\n> have it be something someone else can access externally, it doesn't\n> seem like a feature I can't get almost as simply with existing git\n> commands.  \n\nNot having to manually manage a set of patches may seem small but it\nreduces a barrier that may otherwise be just high enough to hurt\nproductivity in certain situations.\n\n> I guess my final question is what does undo/redo have over saving\n> stuff away in a patch assuming that the patch captures all of the\n> SCM meta-data (the add/move/remove file type commands).  If git\n> doesn't capture all the meta-data in a patch, it would seem better\n> to make it do that and get this as a side-affect.\n> \n>     Thanks,\n>         Kirby\n\nThanks for your comments.\n\nCarl\n\n-- \n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n Carl Baldwin                        Systems VLSI Laboratory\n Hewlett Packard Company\n MS 88                               work: 970 898-1523\n 3404 E. Harmony Rd.                 work: Carl.N.Baldwin@hp.com\n Fort Collins, CO 80525              home: Carl@ecBaldwin.net\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"},{"id":"7759","messageId":"20050825204930.GE7461@birddog.com","threadId":"1637","inReplyTo":"7vmzn5vkg6.fsf@assigned-by-dhcp.cox.net","subject":"Re: [RFC] undo and redo","fromName":"Kirby C. Bohling","fromEmail":"kbohling@birddog.com","sentAt":"2005-08-25T20:49:30Z","receivedAt":"2005-08-25T20:49:30Z","isPatch":false,"sender":{"key":"kbohling@birddog.com","avatar":null},"body":"On Thu, Aug 25, 2005 at 01:19:05PM -0700, Junio C Hamano wrote:\n> \"Kirby C. Bohling\" <kbohling@birddog.com> writes:\n> \n> > I guess my final question is what does undo/redo have over saving\n> > stuff away in a patch assuming that the patch captures all of the\n> > SCM meta-data (the add/move/remove file type commands).  If git\n> > doesn't capture all the meta-data in a patch, it would seem better\n> > to make it do that and get this as a side-affect.\n> \n> One thing that Carl's undo saves that is not easily available in\n> the patch form is the \"what is this patch based on\" information.\n> If you had it, you could do a three-way merge instead of patch\n> application.\n\n> You were at A (time flows from left to right) when somebody\n> (maybe your bright idea) interrupted you.  You take a snapshot\n> of your tree state D as a pair <A, D>, and rewind the tree to\n> original commit A's state:\n> \n>  -->A\n>      \\\n>       D\n> \n> Then you do the work that interrupted you, maybe making commits\n> B and then C:\n> \n>  -->A-->B-->C\n>      \\\n>       D\n> \n> At this point, you would want to restart working on whatever you\n> were doing, which is the difference between A->D applied on top\n> of C.\n> \n> You could keep that information as a patch between A->D and\n> apply it on top of C to get there, which is your approach if I\n> am reading you correctly.  Carl does a three-way merge between C\n> and D using A as the pivot point.\n\n    Just out of curiosity, why isn't the SHA1 of 'A' part of the\ndiff or patch format?  I mean it can't be that hard to add it as a\nsingle line of data that git can parse to extract that piece of\ninformation.  Then a patch would enable you to do the 3-way merge\nyou describe.  If added properly \"regular\" patch would just ignore\nthat line.  The patch would then record that it is relative to 'A'.\n\n    Assuming git could be taught \"git-merge-patch\" and then take use\nthe patch that's saved during the \"undo\" step and has the anchor for\nthe patch to use as the pivot point (as described above).  Life\nshould be good.  There are probably corner cases I don't understand,\nbut it sure looks like if you have the pivot or anchor point for the\npatch embedded in the patch, you have all the needed information to\npull this off.\n\n    I would think this would be generally useful outside of the\ncontext of \"undo/redo\" also.\n\n    Kirby\n"},{"id":"7761","messageId":"20050825210929.GF7461@birddog.com","threadId":"1637","inReplyTo":"20050825203733.GA26539@hpsvcnb.fc.hp.com","subject":"Re: [RFC] undo and redo","fromName":"Kirby C. Bohling","fromEmail":"kbohling@birddog.com","sentAt":"2005-08-25T21:09:29Z","receivedAt":"2005-08-25T21:09:29Z","isPatch":false,"sender":{"key":"kbohling@birddog.com","avatar":null},"body":"On Thu, Aug 25, 2005 at 02:37:33PM -0600, Carl Baldwin wrote:\n> On Thu, Aug 25, 2005 at 02:59:18PM -0500, Kirby C. Bohling wrote:\n> > On Thu, Aug 25, 2005 at 10:32:01AM -0600, Carl Baldwin wrote:\n> > <snip...>\n> > > Another example is if I'm working on a commit and suddenly get a\n> > > brilliant idea for some easy modification that I want to make and commit\n> > > by itself before making this commit.  I can do this easily with\n> > > \n> > >         % git undo\n> > >         % carefully make easy change\n> > >         % git commit\n> > >         % git redo\n> > > \n> > > Having a light-weight alternative like this could make the difference\n> > > between realizing the easy, brilliant idea and forgetting about it on\n> > > the back burner because it was just too cumbersome to make the context\n> > > switch.\n> > > \n> > > The bottom line is that I don't argue against using the existing\n> > > work-flows.  I hope to add the flexibility to use various work-flows to\n> > > fit the job at hand.\n> > > \n> > <snip...>\n> > \n> > [Not much of a git user, but am evaluating it for possible future\n> > usage]... \n> > \n> > Why not just save the changes to a file via a patch.  Just like you\n> > would if you were sending a patch to someone else.  I have the work\n> > flow you are talking about when I use CVS.  I just create a patch,\n> > apply the patch in reverse (or run the command to get you a clean\n> > working tree in the SCM).  Make my unrelated changes commit it.\n> > Then apply the patch, possibly resolve merge conflicts,  and proceed\n> > with finishing my original work.\n> \n> I used to do this with CVS too.  For you and me, people who are patch\n> savy veterans, this is great!  However, as easy as it is I knew very few\n> other developers who even thought about doing it.  In the real world,\n> many people see a huge difference between:\n> \n> git diff-cache > $patchfile\n> cat $patchfile | patch -R -p1\n> do work\n> cat $patchfile | patch -p1\n> \n> AND\n> \n> git undo\n> do work\n> git redo\n> \n> The first one simply never happens with most developers.  Most don't\n> really think of doing something outside the tool.  The second option\n> will likely get used.  Plus, I know at least one person here who is very\n> good with patches and working outside the tool and still would love to\n> have the second approach available.\n\nI guess I can see that.  I just see it as much easier to manage\nmultiple undo-redo states manually.  I mean, I wouldn't make anyone\nuse git directly if the difference between the two commands bothers\nthem.  git seems too low a level.  I would think one of the\nprocelains would be be a better level.  However, having a unified\ninterface for all the porcelains seems a reasonable request.\n\n> \n> Is there something wrong with having flexibility?  It seems most of the\n> criticism of this feature is that there is already a way to accomplish\n> what I want to do.  Tools that can't be used flexibly are not tools that\n> I like to use.  Heck, I'm on UNIX aren't I?\n> \n> Oops, sorry for the rant.  I'm really not in a bad mood... really.  I\n> hope it didn't sound like that :-).  Oh, and I didn't mean to suggest\n> that git is not flexible in other regards.  I think its great!  Moving\n> along...\n> \n> > Assuming your patch creation and application tools capture all the\n> > meta-data the SCM has (which I believe git does), it's pretty simple\n> > to simulate what you want manaully.  With only a handful of\n> > commands.\n> \n> I can simulate git manually too with just a few more commands.  Where's\n> the cutoff?\n\nYes and no.  I meant the order and style of commands was nearly\nidentical.  I meant applying the command line in reverse was the\nonly additional step.  As a workflow, I'd just document it in the\nHOWTO's.  I'm a minimalist in that sense.  Sure, I use more then\necho, redirection and netcat even though in theory I could send you\nthis e-mail with it.  IMHO, the above undo/redo doesn't seem to save\nenough effort to me.  I wouldn't bother learning undo/redo unless it\nwas superior to the patch way, it's just one more thing I'd have to\nremember.\n\n> \n> > I see the appeal of not having manually deal with the files, but\n> > assuming you don't feel it's branch worthy, and you don't want to\n> > have it be something someone else can access externally, it doesn't\n> > seem like a feature I can't get almost as simply with existing git\n> > commands.  \n> \n> Not having to manually manage a set of patches may seem small but it\n> reduces a barrier that may otherwise be just high enough to hurt\n> productivity in certain situations.\n\nI don't mean to discourge it's implementation, I really questioned\nit because I figured there had to be some more subtle implications I\ndidn't understand about undo/redo that patch couldn't capture.  It\nalso seems like multiple levels of undo/redo or undo/redo on\nmultiple branches could get tricky for the user to track and for git\nto be able to display the information to the user sanely.\n\n    Thanks,\n        Kirby\n"},{"id":"7762","messageId":"20050825212851.GA3311@hpsvcnb.fc.hp.com","threadId":"1637","inReplyTo":"20050825204930.GE7461@birddog.com","subject":"Re: [RFC] undo and redo","fromName":"Carl Baldwin","fromEmail":"cnb@fc.hp.com","sentAt":"2005-08-25T21:28:51Z","receivedAt":"2005-08-25T21:28:51Z","isPatch":false,"sender":{"key":"cnb@fc.hp.com","avatar":null},"body":"On Thu, Aug 25, 2005 at 03:49:30PM -0500, Kirby C. Bohling wrote:\n> On Thu, Aug 25, 2005 at 01:19:05PM -0700, Junio C Hamano wrote:\n> > \"Kirby C. Bohling\" <kbohling@birddog.com> writes:\n>     Just out of curiosity, why isn't the SHA1 of 'A' part of the\n> diff or patch format?  I mean it can't be that hard to add it as a\n> single line of data that git can parse to extract that piece of\n> information.  Then a patch would enable you to do the 3-way merge\n> you describe.  If added properly \"regular\" patch would just ignore\n> that line.  The patch would then record that it is relative to 'A'.\n\nNot a bad idea.  It could be ignored in most cases and used when needed.\n\nCarl\n\n>     Assuming git could be taught \"git-merge-patch\" and then take use\n> the patch that's saved during the \"undo\" step and has the anchor for\n> the patch to use as the pivot point (as described above).  Life\n> should be good.  There are probably corner cases I don't understand,\n> but it sure looks like if you have the pivot or anchor point for the\n> patch embedded in the patch, you have all the needed information to\n> pull this off.\n> \n>     I would think this would be generally useful outside of the\n> context of \"undo/redo\" also.\n> \n>     Kirby\n> \n> \n\n-- \n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n Carl Baldwin                        Systems VLSI Laboratory\n Hewlett Packard Company\n MS 88                               work: 970 898-1523\n 3404 E. Harmony Rd.                 work: Carl.N.Baldwin@hp.com\n Fort Collins, CO 80525              home: Carl@ecBaldwin.net\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"},{"id":"7764","messageId":"20050825214208.GB3311@hpsvcnb.fc.hp.com","threadId":"1637","inReplyTo":"20050825210929.GF7461@birddog.com","subject":"Re: [RFC] undo and redo","fromName":"Carl Baldwin","fromEmail":"cnb@fc.hp.com","sentAt":"2005-08-25T21:42:08Z","receivedAt":"2005-08-25T21:42:08Z","isPatch":false,"sender":{"key":"cnb@fc.hp.com","avatar":null},"body":"On Thu, Aug 25, 2005 at 04:09:29PM -0500, Kirby C. Bohling wrote:\n> I guess I can see that.  I just see it as much easier to manage\n> multiple undo-redo states manually.  I mean, I wouldn't make anyone\n> use git directly if the difference between the two commands bothers\n> them.  git seems too low a level.  I would think one of the\n> procelains would be be a better level.  However, having a unified\n> interface for all the porcelains seems a reasonable request.\n\nMaybe Porcelain is the right place for it.  The question would be \"Is it\nimportant that porcelains handle undo/redo in a way that interoperates?\"\n\n> > \n> > Is there something wrong with having flexibility?  It seems most of the\n> > criticism of this feature is that there is already a way to accomplish\n> > what I want to do.  Tools that can't be used flexibly are not tools that\n> > I like to use.  Heck, I'm on UNIX aren't I?\n> > \n> > Oops, sorry for the rant.  I'm really not in a bad mood... really.  I\n> > hope it didn't sound like that :-).  Oh, and I didn't mean to suggest\n> > that git is not flexible in other regards.  I think its great!  Moving\n> > along...\n> > \n> > > Assuming your patch creation and application tools capture all the\n> > > meta-data the SCM has (which I believe git does), it's pretty simple\n> > > to simulate what you want manaully.  With only a handful of\n> > > commands.\n> > \n> > I can simulate git manually too with just a few more commands.  Where's\n> > the cutoff?\n\nThis analogy *was* a bit extreme.\n\nCheers,\nCarl\n\n-- \n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n Carl Baldwin                        Systems VLSI Laboratory\n Hewlett Packard Company\n MS 88                               work: 970 898-1523\n 3404 E. Harmony Rd.                 work: Carl.N.Baldwin@hp.com\n Fort Collins, CO 80525              home: Carl@ecBaldwin.net\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"}]}