summaryrefslogtreecommitdiff
path: root/git-reset.sh
diff options
context:
space:
mode:
Diffstat (limited to 'git-reset.sh')
-rwxr-xr-xgit-reset.sh64
1 files changed, 64 insertions, 0 deletions
diff --git a/git-reset.sh b/git-reset.sh
new file mode 100755
index 0000000000..296f3b779b
--- /dev/null
+++ b/git-reset.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+USAGE='[--mixed | --soft | --hard] [<commit-ish>]'
+. git-sh-setup
+
+tmp=${GIT_DIR}/reset.$$
+trap 'rm -f $tmp-*' 0 1 2 3 15
+
+update=
+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
+ update=-u
+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 $update "$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 -m "reset $reset_type $@" HEAD "$rev"
+
+case "$reset_type" in
+--hard )
+ ;; # Nothing else to do
+--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"