[PATCH] git-subtree: Add prune mode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add prune mode (flag --prune) with the following properties:

* The history must be as clean as possible
* The directory content must be equal to the external module,
  at least when you add/update it[b]
* The subproject should be able to switch back and forth between
  different versions.

[b] A consequence of this is that it loses all changes
    made in the subtree. If they are important you have to extract
    them, apply them and add the subproject back.

As all the history is lost and you never merge commits
'split' is not necessary, but it is basically:

$ git filter-branch --subdirectory-filter $prefix

And normally you will just want to extract the changes with format-patch
and apply them with:

git am -p2

Signed-off-by: Santi Béjar <santi@xxxxxxxxxxx>
---
Hi *,

   here it is a the same patch I send some days before but with documentation.

Santi

 git-subtree.sh  |   29 +++++++++++++++++++++++++++--
 git-subtree.txt |   21 ++++++++++++++++++++-
 2 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/git-subtree.sh b/git-subtree.sh
index 781eef3..766b68b 100755
--- a/git-subtree.sh
+++ b/git-subtree.sh
@@ -27,6 +27,7 @@ onto=         try connecting new tree to an existing one
 rejoin        merge the new branch back into HEAD
  options for 'add', 'merge', 'pull' and 'push'
 squash        merge subtree changes as a single commit
+prune         prune history
 "
 eval $(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)
 
@@ -44,6 +45,7 @@ rejoin=
 ignore_joins=
 annotate=
 squash=
+prune=
 message=
 
 debug()
@@ -92,6 +94,8 @@ while [ $# -gt 0 ]; do
 		--no-ignore-joins) ignore_joins= ;;
 		--squash) squash=1 ;;
 		--no-squash) squash= ;;
+		--prune) prune=1;;
+		--no-prune) prune=;;
 		--) break ;;
 		*) die "Unexpected option: $opt" ;;
 	esac
@@ -110,12 +114,16 @@ if [ -z "$prefix" ]; then
 fi
 
 case "$command" in
-	add) [ -e "$prefix" ] && 
+	add) [ -e "$prefix" -a -z "$prune" ] &&
 		die "prefix '$prefix' already exists." ;;
 	*)   [ -e "$prefix" ] || 
 		die "'$prefix' does not exist; use 'git subtree add'" ;;
 esac
 
+if [ -n "$squash" -a -n "$prune" ] ; then
+	die "Flags --prune and --squash are incompatible"
+fi
+
 dir="$(dirname "$prefix/.")"
 
 if [ "$command" != "pull" -a "$command" != "add" -a "$command" != "push" ]; then
@@ -359,6 +367,17 @@ squash_msg()
 	echo "git-subtree-split: $newsub"
 }
 
+prune_msg()
+{
+	dir="$1"
+	newsub="$2"
+	
+	git show -s --pretty="tformat:Subtree '$dir/': %h %s" $newsub
+	echo
+	echo "git-subtree-dir: $dir"
+	echo "git-subtree-split: $newsub"
+}
+
 toptree_for_commit()
 {
 	commit="$1"
@@ -464,7 +483,7 @@ ensure_clean()
 
 cmd_add()
 {
-	if [ -e "$dir" ]; then
+	if [ -e "$dir" -a -z "$prune" ]; then
 		die "'$dir' already exists.  Cannot add."
 	fi
 
@@ -498,6 +517,9 @@ cmd_add_commit()
 	rev="$1"
 	
 	debug "Adding $dir as '$rev'..."
+	if [ -d "$dir" ]; then
+	    git rm -r -q $dir
+	fi
 	git read-tree --prefix="$dir" $rev || exit $?
 	git checkout -- "$dir" || exit $?
 	tree=$(git write-tree) || exit $?
@@ -513,6 +535,9 @@ cmd_add_commit()
 		rev=$(new_squash_commit "" "" "$rev") || exit $?
 		commit=$(add_squashed_msg "$rev" "$dir" |
 			 git commit-tree $tree $headp -p "$rev") || exit $?
+	elif [ -n "$prune" ]; then
+		commit=$(prune_msg "$dir" "$rev" |
+			 git commit-tree $tree -p $headrev) || exit $?
 	else
 		commit=$(add_msg "$dir" "$headrev" "$rev" |
 			 git commit-tree $tree $headp -p "$rev") || exit $?
diff --git a/git-subtree.txt b/git-subtree.txt
index dbcba31..5a91147 100644
--- a/git-subtree.txt
+++ b/git-subtree.txt
@@ -66,7 +66,8 @@ add::
 	A new commit is created	automatically, joining the imported
 	project's history with your own.  With '--squash', imports
 	only a single commit from the subproject, rather than its
-	entire history.
+	entire history. With '--prune', imports only the contents of
+	the commit from the subproject without any history.
 
 merge::
 	Merge recent changes up to <commit> into the <prefix>
@@ -165,6 +166,24 @@ OPTIONS FOR add, merge, AND pull
 	local repository remain intact and can be later split
 	and send upstream to the subproject.
 
+--prune::
+	Instead of merging the history (full or squashed) from the
+	subtree project, produce only a single commit that
+	reproduce the exact content in the preffix as in the
+	subtree.
+
+	It has similar features as the --squash option, namely
+	reduces the clutter (althougth --prune reduce it even
+	more), helps avoiding problems when the same subproject is
+	include multiple time and can switch back and forth
+	between different version of a subtree.
+
+	The main difference is that with --prune the content of
+	the prefix always matches the content of the subproject,
+	while with --squash it merges you changes with the changes
+	from the subtree. If you want to keep your changes you
+	have to extract them, apply them in the external
+	repository and add the subproject back.
 
 OPTIONS FOR split
 -----------------
-- 
1.7.1.765.gb5868

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]