git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] subtree: add squash handling for split and push

From
Pierre Penninckx <ibizapeanut@gmail.com>
Date
Nov 23, 2013, 20:18 UTC
Message-ID
<C3EF61D4-5274-4A10-9594-4E631D75C3F4@gmail.com>
>From 2763be1fe68d07af60945762178b8494228eb45f Mon Sep 17 00:00:00 2001
From: Pierre Penninckx <ibizapeanut@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" &&
Next: Matthew Ogilvie
Message 1 of 8 in “subtree: add squash handling for split and push”
  1. subtree: add squash handling for split and pushPierre Penninckx, Nov 23, 2013
  2. Matthew OgilvieNov 28, 2013
  3. Pierre PenninckxNov 28, 2013
  4. 1/4 subtree: support split --rejoin --squashMatthew Ogilvie, Dec 7, 2013
  5. 2/4 subtree: allow --squash and --message with pushMatthew Ogilvie, Dec 7, 2013
  6. 3/4 subtree: add --edit optionMatthew Ogilvie, Dec 7, 2013
  7. 4/4 subtree: poor bugfix for split new commits with parents before previous splitMatthew Ogilvie, Dec 7, 2013
  8. Junio C HamanoDec 10, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.