Merge branch 'mh/retag'
[gitweb.git] / git-filter-branch.sh
index 0ff3475525a0d50739f218abbac91eb2dc926430..ffcc408ee5217d7a8f6179a0404ffe387e0dab0f 100755 (executable)
@@ -8,9 +8,6 @@
 # a new branch. You can specify a number of filters to modify the commits,
 # files and trees.
 
-USAGE="git-filter-branch [-d TEMPDIR] [FILTERS] DESTBRANCH [REV-RANGE]"
-. git-sh-setup
-
 warn () {
         echo "$*" >&2
 }
@@ -26,6 +23,20 @@ map()
        fi
 }
 
+# if you run 'skip_commit "$@"' in a commit filter, it will print
+# the (mapped) parents, effectively skipping the commit.
+
+skip_commit()
+{
+       shift;
+       while [ -n "$1" ];
+       do
+               shift;
+               map "$1";
+               shift;
+       done;
+}
+
 # override die(): this version puts in an extra line break, so that
 # the progress is still visible
 
@@ -69,6 +80,24 @@ set_ident () {
        echo "[ -n \"\$GIT_${uid}_NAME\" ] || export GIT_${uid}_NAME=\"\${GIT_${uid}_EMAIL%%@*}\""
 }
 
+# This script can be sourced by the commit filter to get the functions
+test "a$SOURCE_FUNCTIONS" = a1 && return
+this_script="$(cd "$(dirname "$0")"; pwd)"/$(basename "$0")
+export this_script
+
+USAGE="[--env-filter <command>] [--tree-filter <command>] \
+[--index-filter <command>] [--parent-filter <command>] \
+[--msg-filter <command>] [--commit-filter <command>] \
+[--tag-name-filter <command>] [--subdirectory-filter <directory>] \
+[--original <namespace>] [-d <directory>] [-f | --force] \
+[<rev-list options>...]"
+
+. git-sh-setup
+
+git diff-files --quiet &&
+       git diff-index --cached --quiet HEAD ||
+       die "Cannot rewrite branch(es) with a dirty working directory."
+
 tempdir=.git-rewrite
 filter_env=
 filter_tree=
@@ -80,8 +109,9 @@ filter_tag_name=
 filter_subdir=
 orig_namespace=refs/original/
 force=
-while case "$#" in 0) usage;; esac
+while :
 do
+       test $# = 0 && usage
        case "$1" in
        --)
                shift
@@ -125,7 +155,7 @@ do
                filter_msg="$OPTARG"
                ;;
        --commit-filter)
-               filter_commit="$OPTARG"
+               filter_commit='SOURCE_FUNCTIONS=1 . "$this_script";'" $OPTARG"
                ;;
        --tag-name-filter)
                filter_tag_name="$OPTARG"
@@ -134,7 +164,7 @@ do
                filter_subdir="$OPTARG"
                ;;
        --original)
-               orig_namespace="$OPTARG"
+               orig_namespace=$(expr "$OPTARG/" : '\(.*[^/]\)/*$')/
                ;;
        *)
                usage
@@ -170,13 +200,9 @@ do
        esac
 done < "$tempdir"/backup-refs
 
-case "$GIT_DIR" in
-/*)
-       ;;
-*)
-       GIT_DIR="$(pwd)/../../$GIT_DIR"
-       ;;
-esac
+ORIG_GIT_DIR="$GIT_DIR"
+ORIG_GIT_WORK_TREE="$GIT_WORK_TREE"
+ORIG_GIT_INDEX_FILE="$GIT_INDEX_FILE"
 export GIT_DIR GIT_WORK_TREE=.
 
 # These refs should be updated if their heads were rewritten
@@ -298,7 +324,7 @@ do
        # Assign the boundarie(s) in the set of rewritten commits
        # as the replacement commit(s).
        # (This would look a bit nicer if --not --stdin worked.)
-       for p in $((cd "$workdir"/../map; ls | sed "s/^/^/") |
+       for p in $( (cd "$workdir"/../map; ls | sed "s/^/^/") |
                git rev-list $ref --boundary --stdin |
                sed -n "s/^-//p")
        do
@@ -394,4 +420,12 @@ echo
 test $count -gt 0 && echo "These refs were rewritten:"
 git show-ref | grep ^"$orig_namespace"
 
+unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE
+test -z "$ORIG_GIT_DIR" || GIT_DIR="$ORIG_GIT_DIR" && export GIT_DIR
+test -z "$ORIG_GIT_WORK_TREE" || GIT_WORK_TREE="$ORIG_GIT_WORK_TREE" &&
+       export GIT_WORK_TREE
+test -z "$ORIG_GIT_INDEX_FILE" || GIT_INDEX_FILE="$ORIG_GIT_INDEX_FILE" &&
+       export GIT_INDEX_FILE
+git read-tree -u -m HEAD
+
 exit $ret