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