Hello,

So, one thing that I liked about GNU Arch when I tried it out was the
ability to undo and redo changes in the local working copy.  I decided
to try to do this with git.  What I have is preliminary.  I'm sure it
could use some work.

So, I started with the assumption that all changes in the working copy
have been updated to the cache.  My scripts check this (with
git-diff-files) and abort if this is not the case.

Undo calls git-write-tree to write the changes to the object store.  It
stores that tree's hash and the current HEAD's tree's hash in a file.
Then it reverts the working copy to HEAD.

Redo grabs these two trees from the file, does git-write-tree to produce
a third tree and merges the three using the old HEAD's tree as the base
of the merge.  This way, new commits can happen and the local copy can
be modified since the undo and it should still work assuming no
conflicts emerge.

Attached are the two scripts.  Comments and criticism are welcome.

Cheers,
Carl

-- 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 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]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#!/bin/sh

. git-sh-setup-script || die "Not a git archive"

if [ -n "$(git-diff-files)" ]; then
    echo The following files should be updated!
    echo
    git-diff-files | awk '{print $6}'
fi

undostack=$GIT_DIR/undostack

if [ ! -s $undostack ]; then
    echo "No undo information in $undostack"
else
    # Read the top of the stack
    basetree=$(cat $undostack | tail -n 2 | head -n 1)
    redotree=$(cat $undostack | tail -n 1)

    # Pop the stack
    cat $undostack | head -n -2 > $undostack.tmp
    mv $undostack{.tmp,}

    currenttree=$(git-write-tree)

    git-read-tree -u -m $basetree $currenttree $redotree
    git-merge-cache git-merge-one-file-script -a
fi
#!/bin/sh

. git-sh-setup-script || die "Not a git archive"

if [ -n "$(git-diff-files)" ]; then
    echo The following files should be updated!
    echo
    git-diff-files | awk '{print $6}'
fi

undostack=$GIT_DIR/undostack

headtree=$(git-cat-file commit $(cat $GIT_DIR/HEAD) | head -n 1 | sed -e 
's/tree //')
undotree=$(git-write-tree)

if [ $headtree == $undotree ]; then
    echo There are no changes to undo.
else
    {
       echo $headtree
       echo $undotree
    } >> $undostack

    echo Saved current state as tree $undotree.
    echo Reverting to HEAD, $headtree...

    git-checkout-script -f
fi

Reply via email to