>From 2763be1fe68d07af60945762178b8494228eb45f Mon Sep 17 00:00:00 2001
From: Pierre Penninckx <ibizapea...@gmail.com>
Date: Sat, 23 Nov 2013 20:03:20 +0100
Subject: [PATCH] subtree: add squash handling for split and push

The documentation of subtree says that the --squash option can be used
for add, merge, split and push subtree commands but only add and merge
is implemented.

cmd_push() simply forwards the --squash argument to subtree split. All
the job is done by cmd_split().

cmd_split() first lets split do it's job: finding which commits need to
be extracted. Now we remember which commit is the parent of the first
extracted commit. When this step is done, cmd_split() generates a squash
of the new commits, starting from the aforementioned parent to the last
extracted commit. This new commit's sha1 is then used for the rest of
the script.

Tests verify that `git subtree split/push --squash` makes only one
commit where `git subtree split/push` without squash makes two.
---
 contrib/subtree/git-subtree.sh     | 20 ++++++++++++++++++-
 contrib/subtree/t/t7900-subtree.sh | 40 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index 7d7af03..76eb136 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
@@ -183,6 +183,7 @@ cache_set()
        newrev="$2"
        if [ "$oldrev" != "latest_old" \
             -a "$oldrev" != "latest_new" \
+            -a "$oldrev" != "firstnewparents" \
             -a -e "$cachedir/$oldrev" ]; then
                die "cache for $oldrev already exists!"
        fi
@@ -603,6 +604,10 @@ cmd_split()
                debug "  parents: $parents"
                newparents=$(cache_get $parents)
                debug "  newparents: $newparents"
+               if [ -z "$(cache_get firstnewparents)" ]; then
+                       cache_set firstnewparents $newparents
+                       debug "  firstnewparents: $(cache_get firstnewparents)"
+               fi

                tree=$(subtree_for_commit $rev "$dir")
                debug "  tree is: $tree"
@@ -625,11 +630,18 @@ cmd_split()
                cache_set latest_new $newrev
                cache_set latest_old $rev
        done || exit $?
+
        latest_new=$(cache_get latest_new)
        if [ -z "$latest_new" ]; then
                die "No new revisions were found"
        fi

+       if [ -n "$squash" ]; then
+               from=$(cache_get firstnewparents)
+               latest_new=$(new_squash_commit "$from" "$from" "$latest_new") 
|| exit $?
+               debug "New squash commit: $latest_new"
+       fi
+
        if [ -n "$rejoin" ]; then
                debug "Merging split branch into HEAD..."
                latest_old=$(cache_get latest_old)
@@ -711,11 +723,17 @@ cmd_push()
        if [ $# -ne 2 ]; then
            die "You must provide <repository> <refspec>"
        fi
+
+       squash_cmd=
+       if [ -n "$squash" ]; then
+           squash_cmd="--squash"
+       fi
+
        if [ -e "$dir" ]; then
            repository=$1
            refspec=$2
            echo "git push using: " $repository $refspec
-           localrev=$(git subtree split --prefix="$prefix") || die
+           localrev=$(git subtree split --prefix="$prefix" $squash_cmd) || die
            git push $repository $localrev:refs/heads/$refspec
        else
            die "'$dir' must already exist. Try 'git subtree add'."
diff --git a/contrib/subtree/t/t7900-subtree.sh 
b/contrib/subtree/t/t7900-subtree.sh
index 66ce4b0..04eea94 100755
--- a/contrib/subtree/t/t7900-subtree.sh
+++ b/contrib/subtree/t/t7900-subtree.sh
@@ -31,6 +31,16 @@ check_equal()
        fi
 }

+check_not_equal()
+{
+        check_equal "$1" "$2"
+        if [ $? -eq 0 ]; then
+                return 1
+        else
+                return 0
+        fi
+}
+
 fixnl()
 {
        t=""
@@ -161,6 +171,36 @@ test_expect_success 'fetch new subproj history' '
         git branch sub2 FETCH_HEAD
 '

+test_expect_success 'check that split and split --squash produce different 
commits' '
+        split=$(git subtree split --prefix=subdir) &&
+        split_squash=$(git subtree split --prefix=subdir --squash) &&
+        check_not_equal "$split" "$split_squash"
+'
+
+test_expect_success 'check that split and split --squash produce same diff' '
+        split=$(git subtree split --prefix=subdir) &&
+        split_squash=$(git subtree split --prefix=subdir --squash) &&
+        split_diff=$(git diff sub1 $split) &&
+        split_squash_diff=$(git diff sub1 $split_squash) &&
+        check_equal "$split_diff" "$split_squash_diff"
+'
+
+test_expect_success 'check that push introduces two commits in subproj' '
+        git subtree push --prefix=subdir subproj mainline &&
+        cd subproj &&
+        check_equal "$(git rev-parse mainline~2)" "$(git rev-parse sub1)" &&
+        git branch -D mainline &&
+        cd ..
+'
+
+test_expect_success 'check that push --squash introduces only one commit in 
subproj' '
+        git subtree push --prefix=subdir subproj mainline --squash &&
+        cd subproj &&
+        check_equal "$(git rev-parse mainline^)" "$(git rev-parse sub1)" &&
+        git branch -D mainline &&
+        cd ..
+'
+
 test_expect_success 'check if --message works for merge' '
         git subtree merge --prefix=subdir -m "Merged changes from subproject" 
sub2 &&
         check_equal ''"$(last_commit_message)"'' "Merged changes from 
subproject" &&
--
1.8.3.4 (Apple Git-47)

Signed-off-by: Pierre Penninckx <ibizapea...@gmail.com>--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to