Add a new --rejoin option.
authorAvery Pennarun <apenwarr@gmail.com>
Fri, 24 Apr 2009 19:48:41 +0000 (15:48 -0400)
committerAvery Pennarun <apenwarr@gmail.com>
Fri, 24 Apr 2009 19:48:41 +0000 (15:48 -0400)
The idea is to join the new split branch back into this one, so future
splits can append themselves to the old split branch.  We mark the split
branch's history in our merge commit, so we can pull it back out later.

git-subtree.sh

index 5f8b0f6c598601756a68fe9df5cc065b791627d9..a31b0b2f6a6ebc11e1c21c61a934ddb68d7275da 100755 (executable)
@@ -2,10 +2,10 @@
 #
 # git-subtree.sh: split/join git repositories in subdirectories of this one
 #
-# Copyright (c) 2009 Avery Pennarun <apenwarr@gmail.com>
+# Copyright (C) 2009 Avery Pennarun <apenwarr@gmail.com>
 #
 OPTS_SPEC="\
-git subtree split <revisions> -- <subdir>
+git subtree split [--rejoin] [--onto rev] <commit...> -- <path>
 git subtree merge 
 
 git subtree does foo and bar!
@@ -13,6 +13,8 @@ git subtree does foo and bar!
 h,help   show the help
 q        quiet
 v        verbose
+onto=    existing subtree revision to connect, if any
+rejoin   merge the new branch back into HEAD
 "
 eval $(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)
 . git-sh-setup
@@ -20,6 +22,8 @@ require_work_tree
 
 quiet=
 command=
+onto=
+rejoin=
 
 debug()
 {
@@ -42,9 +46,12 @@ assert()
 
 while [ $# -gt 0 ]; do
        opt="$1"
+       debug "option: $1"
        shift
        case "$opt" in
                -q) quiet=1 ;;
+               --onto) onto="$1"; shift ;;
+               --rejoin) rejoin=1 ;;
                --) break ;;
        esac
 done
@@ -93,7 +100,9 @@ cache_set()
 {
        oldrev="$1"
        newrev="$2"
-       if [ "$oldrev" != "latest" -a -e "$cachedir/$oldrev" ]; then
+       if [ "$oldrev" != "latest_old" \
+            -a "$oldrev" != "latest_new" \
+            -a -e "$cachedir/$oldrev" ]; then
                die "cache for $oldrev already exists!"
        fi
        echo "$newrev" >"$cachedir/$oldrev"
@@ -111,12 +120,29 @@ copy_commit()
                read GIT_COMMITTER_NAME
                read GIT_COMMITTER_EMAIL
                read GIT_COMMITTER_DATE
-               export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
-               export GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL GIT_COMMITTER_DATE
+               export  GIT_AUTHOR_NAME \
+                       GIT_AUTHOR_EMAIL \
+                       GIT_AUTHOR_DATE \
+                       GIT_COMMITTER_NAME \
+                       GIT_COMMITTER_EMAIL \
+                       GIT_COMMITTER_DATE
                git commit-tree "$2" $3  # reads the rest of stdin
        ) || die "Can't copy commit $1"
 }
 
+merge_msg()
+{
+       dir="$1"
+       latest_old="$2"
+       latest_new="$3"
+       cat <<-EOF
+               Split changes from '$dir/' into commit '$latest_new'
+               
+               git-subtree-dir: $dir
+               git-subtree-includes: $latest_old
+       EOF
+}
+
 cmd_split()
 {
        debug "Splitting $dir..."
@@ -140,14 +166,23 @@ cmd_split()
                        newrev=$(copy_commit $rev $tree "$p") || exit $?
                        debug "  newrev is: $newrev"
                        cache_set $rev $newrev
-                       cache_set latest $newrev
+                       cache_set latest_new $newrev
+                       cache_set latest_old $rev
                done || exit $?
        done || exit $?
-       latest=$(cache_get latest)
-       if [ -z "$latest" ]; then
+       latest_new=$(cache_get latest_new)
+       if [ -z "$latest_new" ]; then
                die "No new revisions were found"
        fi
-       echo $latest
+       
+       if [ -n "$rejoin" ]; then
+               debug "Merging split branch into HEAD..."
+               latest_old=$(cache_get latest_old)
+               git merge -s ours \
+                       -m "$(merge_msg $dir $latest_old $latest_new)" \
+                       $latest_new
+       fi
+       echo $latest_new
        exit 0
 }