Well, both are good ideas. Both are stack oriented, though. I see what you mean about adding an undo directory to .git/refs/. I will do some tests... (read further)
On Wed, Aug 24, 2005 at 03:48:21PM -0700, Junio C Hamano wrote: > Daniel Barkalow <[EMAIL PROTECTED]> writes: > > > Generally, each subdirectory of refs/ has refs to objects of the same > > type, and heads/ is commits, but other directories are other things. tags/ > > is all tag objects, and you could have undo/ be trees. > > That's OK from the prune front, but I am not sure what the > ramifications of this for pulling, pushing, and resolving. > I would not recommend it without really thinking it through. So, I've tried cloning, pulling to|from, pushing to|from and resolving merges in a repository with undo information stored under .git/refs/undo. None of these operations seem to notice the existence of this directory. I think this is good. The cloned repository does not end up 'inheriting' the undo directory (as I would expect) but does end up with any objects reachable from the undo tree. However, these objects get pruned on the next 'git prune'. This, I think, is minor. Pull seems to ignore the undo directory and, of course, the objects reachable by the undo trees. This is what I expected and wanted. Resolving merges worked as expected. I think undo trees should be considered local to the repository and this is the behavior that I observed. I think this is a positive. Before reading your message, I polished up the scripts and changed them so that they store the undo tree and the base tree's hashes in the .git/refs/undo directory. Also, git-redo-script can take an optional argument...the name of the undo to replay. I guess undo should also take an optional argument to give the undo tree some symbolic name. I think this is getting rather solid. Let me know what you think. Here is the git-undo-script: #!/bin/sh . git-sh-setup-script || die "Not a git archive" git-update-cache --refresh || exit 1 undodir=$GIT_DIR/refs/undo undoinfo=$undodir/$(date +%Y.%m.%d.%H.%M.%S) headtree=$(git-cat-file commit $(cat $GIT_DIR/HEAD) | sed -n 's/^tree //p') undotree=$(git-write-tree) if [ $headtree == $undotree ]; then echo There are no changes to undo. else mkdir -p $(dirname $undoinfo) echo $headtree > $undoinfo.base echo $undotree > $undoinfo.undo echo Saved current state in $undodir as $(basename $undoinfo) git-read-tree -m -u $undotree $headtree fi # --- SNIP --- and here, is the redo script #!/bin/sh . git-sh-setup-script || die "Not a git archive" git-update-cache --refresh || exit 1 usage () { echo >&2 "Usage: git-redo-script [undo name]" exit 1 } undodir=$GIT_DIR/refs/undo # If an 'undo name' was given on the command line then try to use it. # If not, then automatically pick the most recent undo. undoinfo= case "$#" in 0) undoinfo=$undodir/$(ls -tr $undodir | sed -n 's/\.undo$//p' | tail -n 1) ;; 1) if [ -s $undodir/$1 ]; then undoinfo=$(echo $undodir/$1 | sed -n "s/\.[^.]*$//p") elif [ -s $undodir/$1.undo -a -s $undodir/$1.base ]; then undoinfo=$undodir/$1 else usage fi ;; *) usage ;; esac # Perform a three-way merge between the base tree, undo tree and current index if [ ! -s $undoinfo.undo -o ! -s $undoinfo.base ]; then echo "No undo information available" else git-read-tree -u -m $(cat $undoinfo.base) $(cat $undoinfo.undo) $(git-write-tree) git-merge-cache git-merge-one-file-script -a rm -f $undoinfo.* test -z "$(ls $undodir)" && rmdir $undodir fi # --- SNIP --- I would be glad to write up documentation and provide a patch. Cheers, Carl > Also note that tags/ is not all tag objects. I think "git tag" > by default creates a lightweight tag, not an annotated kind. > > I think you could do either one of two things. As usual, totally > untested. Just thinking aloud. > > (1) A hack. > > - Have a single "undo-redo" branch, which was forked from > somewhere on the "master" branch. > > - When doing "undo", make a commit that has the current top > of undo-redo branch as the first parent and the current > HEAD commit as the second parent, using the tree that > represents your snapshot, to grow "undo-redo" branch. > > No, this commit does *not* represent a merge, but I am > abusing the capability to record more than one parent > commits. > > - When running "redo", you would want a handy way to name > what to redo. You can say "undo-redo~N" to mean "Nth > from the top of undo-redo branch. > > Your implementation of "redo" can either be (patch way): > > git-diff-tree -p undo-redo~N^ undo-redo~N | git apply --index > > or (merge way): > > git-read-tree -m undo-redo~N^2 undo-redo~N HEAD && > git-merge-cache -o git-merge-one-file-script -a > > (2) Try StGIT. > > -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Carl Baldwin Systems VLSI Laboratory Hewlett Packard Company MS 88 work: 970 898-1523 3404 E. Harmony Rd. work: [EMAIL PROTECTED] Fort Collins, CO 80525 home: [EMAIL PROTECTED] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html