Thread (11 messages) flat view 11 messages, 4 authors, 2016-06-15

Re: [RFC PATCH 3/3] filter-branch: support --submodule-filter

From: Thomas Rast <hidden>
Date: 2016-06-15 22:50:19
Subsystem: the rest · Maintainer: Linus Torvalds

Please don't top-post.  (There's nothing wrong with snipping the whole
message if it does not really relate, as in this case.)

Ccs for the patch at the end; I don't really care much but I could
roll all of it into a sort of "submodule tools" series for g-f-b, so
if you like it, speak up.

Jeffrey Phillips Freeman wrote:
So im kinda new with all this so bare with me guys. I wanted to figure 
out how to apply these patches, now i know i can use git to do this with 
its patch command and such. However i was curious does this exist as a 
branch somewhere official or semi-official?
Not really.

You can dig through the mailing list archives and also e.g.
gitworkflows to see how Junio handles incoming patches, but for series
like this you usually have to apply them yourself.  I deliberately
flagged it RFC because I wanted to get some feedback ... and because I
would have had to spend more time on it for docs&tests.
I currently seem to be using
--split-submodule which is itself in a git repo i have (which i want to 
also find its source repo so i can keep up to date with it).
For others reading this, I wrote --split-submodule also based on an
IRC request from Jeffrey.  The patch is at the end.  But it's way less
thought through than the --{dump,load}-map feature.  In particular
I've been wondering whether it's possible to use the latter to
implement --split-submodule as a fairly concise index filter.
So applying 
the patch itself might be somewhat troubling due to conflicts, therefore 
id like to actually merge in a remote branch to keep things easy. So can 
you guys point me to which repo would be best for me to keep up to date 
with this would be?
You'll get the same conflicts from merging two little branches with
the features on them as with a 'git am -3'.

Many patches are never pushed to a public repo (there are some notable
exceptions in longer-running work).  The hassle of sending and
applying email is far outweighed by the ease of review.  Many reviews
happen without applying the series at all.  That I pushed both of them
to a public repo was an exception for your convenience.

--- 8< ---
Subject: TOY PATCH: filter-branch --split-submodule

Sometimes it makes sense to split out a path not as a subdirectory
(that would be merged by subtree-merge), but as a submodule.  Since
git objects are just shaped in the right way, this is actually quite
easy to do in a way that maintains the correct history relations:

When splitting out DIR in commit C, the submodule commit has tree
C:DIR and the rewritten superproject commit C' gets a submodule entry
at C:DIR instead.

Parent rewriting is done in the obvious way: submodule commits have
their corresponding submodule-changing ancestors as parents.  These
are easy to fetch since we can basically use $(map C^):DIR.

This is a toy patch because of its terrible interface: you will still
have to put the submodule in place.  As a start, you can

  git clone . DIR
  ( cd DIR && git reset --hard $(git rev-parse :DIR) )

to get a sub-repo set to the correct commit.

Signed-off-by: Thomas Rast <redacted>
diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index 962a93b..329d85c 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -191,6 +191,9 @@ do
 		filter_subdir="$OPTARG"
 		remap_to_ancestor=t
 		;;
+	--split-submodule)
+		split_submodule="$OPTARG"
+		;;
 	--original)
 		orig_namespace=$(expr "$OPTARG/" : '\(.*[^/]\)/*$')/
 		;;
@@ -349,6 +352,43 @@ while read commit parents; do
 	eval "$filter_index" < /dev/null ||
 		die "index filter failed: $filter_index"
 
+	if test -n "$split_submodule"; then
+		sub_differs=
+		sub_parents=
+		sub_commit=
+		submodule="$(git rev-parse --verify $commit:$split_submodule 2>/dev/null)"
+		if test -z "$parents"; then
+			if test -n "$submodule"; then
+				sub_differs=t
+			fi
+		fi
+		for parent in $parents; do
+			if ! test "$(git rev-parse --verify $parent:$split_submodule 2>/dev/null)" = "$submodule"; then
+				sub_differs=t
+			fi
+			for reparent in $(map "$parent"); do
+				p="$(git rev-parse --verify $reparent:$split_submodule 2>/dev/null)"
+				if test -n "$p"; then
+					sub_parents="$sub_parents -p $p"
+				fi
+			done
+		done
+		if test -n "$sub_differs"; then
+			sub_commit="$(sed -e '1,/^$/d' <../commit |
+				      git commit-tree $submodule $sub_parents)" || exit
+		else
+			for parent in $parents; do
+				sub_commit="$(git rev-parse --verify "$(map "$parent")":$split_submodule 2>/dev/null)"
+				break
+			done
+		fi
+		if test -n "$sub_commit"; then
+			git update-index --add --replace --cacheinfo 160000 $sub_commit "$split_submodule" || exit
+		else
+			git update-index --remove "$split_submodule"
+		fi
+	fi
+
 	parentstr=
 	for parent in $parents; do
 		for reparent in $(map "$parent"); do
-- 
Thomas Rast
trast@{inf,student}.ethz.ch
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help