git-reset.shon commit Merge http://www.kernel.org/pub/scm/gitk/gitk (8fc66df)
   1#!/bin/sh
   2. git-sh-setup || die "Not a git archive"
   3
   4usage () {
   5        die 'Usage: git reset [--mixed | --soft | --hard]  [<commit-ish>]'
   6}
   7
   8tmp=/var/tmp/reset.$$
   9trap 'rm -f $tmp-*' 0 1 2 3 15
  10
  11reset_type=--mixed
  12case "$1" in
  13--mixed | --soft | --hard)
  14        reset_type="$1"
  15        shift
  16        ;;
  17-*)
  18        usage ;;
  19esac
  20
  21rev=$(git-rev-parse --verify --default HEAD "$@") || exit
  22rev=$(git-rev-parse --verify $rev^0) || exit
  23
  24# We need to remember the set of paths that _could_ be left
  25# behind before a hard reset, so that we can remove them.
  26if test "$reset_type" = "--hard"
  27then
  28        {
  29                git-ls-files --stage -z
  30                git-rev-parse --verify HEAD 2>/dev/null &&
  31                git-ls-tree -r -z HEAD
  32        } | perl -e '
  33            use strict;
  34            my %seen;
  35            $/ = "\0";
  36            while (<>) {
  37                chomp;
  38                my ($info, $path) = split(/\t/, $_);
  39                next if ($info =~ / tree /);
  40                if (!$seen{$path}) {
  41                        $seen{$path} = 1;
  42                        print "$path\0";
  43                }
  44            }
  45        ' >$tmp-exists
  46fi
  47
  48# Soft reset does not touch the index file nor the working tree
  49# at all, but requires them in a good order.  Other resets reset
  50# the index file to the tree object we are switching to.
  51if test "$reset_type" = "--soft"
  52then
  53        if test -f "$GIT_DIR/MERGE_HEAD" ||
  54           test "" != "$(git-ls-files --unmerged)"
  55        then
  56                die "Cannot do a soft reset in the middle of a merge."
  57        fi
  58else
  59        git-read-tree --reset "$rev" || exit
  60fi
  61
  62# Any resets update HEAD to the head being switched to.
  63if orig=$(git-rev-parse --verify HEAD 2>/dev/null)
  64then
  65        echo "$orig" >"$GIT_DIR/ORIG_HEAD"
  66else
  67        rm -f "$GIT_DIR/ORIG_HEAD"
  68fi
  69git-update-ref HEAD "$rev"
  70
  71case "$reset_type" in
  72--hard )
  73        # Hard reset matches the working tree to that of the tree
  74        # being switched to.
  75        git-checkout-index -f -u -q -a
  76        git-ls-files --cached -z |
  77        perl -e '
  78                use strict;
  79                my (%keep, $fh);
  80                $/ = "\0";
  81                while (<STDIN>) {
  82                        chomp;
  83                        $keep{$_} = 1;
  84                }
  85                open $fh, "<", $ARGV[0]
  86                        or die "cannot open $ARGV[0]";
  87                while (<$fh>) {
  88                        chomp;
  89                        if (! exists $keep{$_}) {
  90                                # it is ok if this fails -- it may already
  91                                # have been culled by checkout-index.
  92                                unlink $_;
  93                        }
  94                }
  95        ' $tmp-exists
  96        ;;
  97--soft )
  98        ;; # Nothing else to do
  99--mixed )
 100        # Report what has not been updated.
 101        git-update-index --refresh
 102        ;;
 103esac
 104
 105rm -f "$GIT_DIR/MERGE_HEAD"