#!/bin/sh USAGE='[--mixed | --soft | --hard] [<commit-ish>]' . git-sh-setup tmp=${GIT_DIR}/reset.$$ trap 'rm -f $tmp-*' 0 1 2 3 15 reset_type=--mixed case "$1" in --mixed | --soft | --hard) reset_type="$1" shift ;; -*) usage ;; esac rev=$(git-rev-parse --verify --default HEAD "$@") || exit rev=$(git-rev-parse --verify $rev^0) || exit # We need to remember the set of paths that _could_ be left # behind before a hard reset, so that we can remove them. if test "$reset_type" = "--hard" then { git-ls-files --stage -z git-rev-parse --verify HEAD 2>/dev/null && git-ls-tree -r -z HEAD } | perl -e ' use strict; my %seen; $/ = "\0"; while (<>) { chomp; my ($info, $path) = split(/\t/, $_); next if ($info =~ / tree /); if (!$seen{$path}) { $seen{$path} = 1; print "$path\0"; } } ' >$tmp-exists fi # Soft reset does not touch the index file nor the working tree # at all, but requires them in a good order. Other resets reset # the index file to the tree object we are switching to. if test "$reset_type" = "--soft" then if test -f "$GIT_DIR/MERGE_HEAD" || test "" != "$(git-ls-files --unmerged)" then die "Cannot do a soft reset in the middle of a merge." fi else git-read-tree --reset "$rev" || exit fi # Any resets update HEAD to the head being switched to. if orig=$(git-rev-parse --verify HEAD 2>/dev/null) then echo "$orig" >"$GIT_DIR/ORIG_HEAD" else rm -f "$GIT_DIR/ORIG_HEAD" fi git-update-ref HEAD "$rev" case "$reset_type" in --hard ) # Hard reset matches the working tree to that of the tree # being switched to. git-checkout-index -f -u -q -a git-ls-files --cached -z | perl -e ' use strict; my (%keep, $fh); $/ = "\0"; while (<STDIN>) { chomp; $keep{$_} = 1; } open $fh, "<", $ARGV[0] or die "cannot open $ARGV[0]"; while (<$fh>) { chomp; if (! exists $keep{$_}) { # it is ok if this fails -- it may already # have been culled by checkout-index. unlink $_; while (s|/[^/]*$||) { rmdir($_) or last; } } } ' $tmp-exists ;; --soft ) ;; # Nothing else to do --mixed ) # Report what has not been updated. git-update-index --refresh ;; esac rm -f "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/rr-cache/MERGE_RR"