Merge branch 'master' of git://github.com/psionides/git-subtree
[gitweb.git] / git-subtree.sh
index 96118735b2c9da6867579dd19ae314add87f8b6d..66ce251eaafc41e607ee0dec37e8b172bf8f6c93 100755 (executable)
@@ -16,7 +16,7 @@ git subtree split --prefix=<prefix> <commit...>
 h,help        show the help
 q             quiet
 d             show debug messages
-p,prefix=     the name of the subdir to split out
+P,prefix=     the name of the subdir to split out
 m,message=    use the given message as the commit message for the merge commit
  options for 'split'
 annotate=     add a prefix to commit message of new commits
@@ -78,7 +78,7 @@ while [ $# -gt 0 ]; do
                --annotate) annotate="$1"; shift ;;
                --no-annotate) annotate= ;;
                -b) branch="$1"; shift ;;
-               -p) prefix="$1"; shift ;;
+               -P) prefix="$1"; shift ;;
                -m) message="$1"; shift ;;
                --no-prefix) prefix= ;;
                --onto) onto="$1"; shift ;;
@@ -161,6 +161,20 @@ rev_exists()
        fi
 }
 
+rev_is_descendant_of_branch()
+{
+       newrev="$1"
+       branch="$2"
+       branch_hash=$(git rev-parse $branch)
+       match=$(git rev-list -1 $branch_hash ^$newrev)
+
+       if [ -z "$match" ]; then
+               return 0
+       else
+               return 1
+       fi
+}
+
 # if a commit doesn't have a parent, this might not work.  But we only want
 # to remove the parent from the rev-list, and since it doesn't exist, it won't
 # be there anyway, so do nothing in that case.
@@ -303,7 +317,7 @@ rejoin_msg()
                commit_message="Split '$dir/' into commit '$latest_new'"
        fi
        cat <<-EOF
-               $message
+               $commit_message
                
                git-subtree-dir: $dir
                git-subtree-mainline: $latest_old
@@ -476,10 +490,6 @@ cmd_add()
 
 cmd_split()
 {
-       if [ -n "$branch" ] && rev_exists "refs/heads/$branch"; then
-               die "Branch '$branch' already exists."
-       fi
-
        debug "Splitting $dir..."
        cache_setup || exit $?
        
@@ -510,7 +520,8 @@ cmd_split()
        eval "$grl" |
        while read rev parents; do
                revcount=$(($revcount + 1))
-               say -n "$revcount/$revmax ($createcount)\r"
+               say -n "$revcount/$revmax ($createcount)
+"
                debug "Processing commit: $rev"
                exists=$(cache_get $rev)
                if [ -n "$exists" ]; then
@@ -527,7 +538,10 @@ cmd_split()
                
                # ugly.  is there no better way to tell if this is a subtree
                # vs. a mainline commit?  Does it matter?
-               [ -z $tree ] && continue
+               if [ -z $tree ]; then
+                       cache_set $rev $rev
+                       continue
+               fi
 
                newrev=$(copy_or_skip "$rev" "$tree" "$newparents") || exit $?
                debug "  newrev is: $newrev"
@@ -548,9 +562,16 @@ cmd_split()
                        $latest_new >&2 || exit $?
        fi
        if [ -n "$branch" ]; then
-               git update-ref -m 'subtree split' "refs/heads/$branch" \
-                       $latest_new "" || exit $?
-               say "Created branch '$branch'"
+               if rev_exists "refs/heads/$branch"; then
+                       if ! rev_is_descendant_of_branch $latest_new $branch; then
+                               die "Branch '$branch' is not an ancestor of commit '$latest_new'."
+                       fi
+                       action='Updated'
+               else
+                       action='Created'
+               fi
+               git update-ref -m 'subtree split' "refs/heads/$branch" $latest_new || exit $?
+               say "$action branch '$branch'"
        fi
        echo $latest_new
        exit 0