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

[PATCH v2 2/2] filter-branch: nearest-ancestor rewriting outside subdir filter

From
Thomas Rast <trast@student.ethz.ch>
Date
Oct 21, 2009, 18:28 UTC
Message-ID
<9676b8307ce61d9b3bf79beff7f4b9a04220154f.1256149428.git.trast@student.ethz.ch>
In-Reply-To
<95535b01e2181d321190c6d93b2834188612a389.1256149428.git.trast@student.ethz.ch>

Since a0e4639 (filter-branch: fix ref rewriting with --subdirectory-filter, 2008-08-12) git-filter-branch has done nearest-ancestor rewriting when using a --subdirectory-filter.

However, that rewriting strategy is also a useful building block in other tasks. For example, if you want to split out a subset of files from your history, you would typically call

  git filter-branch -- <refs> -- <files>

But this fails for all refs that do not point directly to a commit that affects <files>, because their referenced commit will not be rewritten and the ref remains untouched.

The code was already there for the --subdirectory-filter case, so just introduce an option that enables it independently.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---

Evidently I shouldn't send any patches after dinner, or before, for that matter (but for lack of wifi in the restaurant, *during* dinner is not an option either). Or at least I shouldn't re-read them after sending :-(

v1 had a completely misplaced option parsing for the new option. Very embarrassing. Really.

I also sneak fixed the commit message above; you only need two -- if you want rev-list options, e.g.,

  git filter-branch -- --all -- README

in which case the first one of course needs to appear before the first <refs> argument.

 Documentation/git-filter-branch.txt |   13 ++++++++++++-
 git-filter-branch.sh                |    9 ++++++++-
 t/t7003-filter-branch.sh            |   18 ++++++++++++++++++
 3 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt
index 2b40bab..394a77a 100644
--- a/Documentation/git-filter-branch.txt
+++ b/Documentation/git-filter-branch.txt
@@ -159,7 +159,18 @@ to other tags will be rewritten to point to the underlying commit.
 --subdirectory-filter <directory>::
 	Only look at the history which touches the given subdirectory.
 	The result will contain that directory (and only that) as its
-	project root.
+	project root.  Implies --remap-to-ancestor.
+
+--remap-to-ancestor::
+	Rewrite refs to the nearest rewritten ancestor instead of
+	ignoring them.
++
+Normally, positive refs on the command line are only changed if the
+commit they point to was rewritten.  However, you can limit the extent
+of this rewriting by using linkgit:rev-list[1] arguments, e.g., path
+limiters.  Refs pointing to such excluded commits would then normally
+be ignored.  With this option, they are instead rewritten to point at
+the nearest ancestor that was not excluded.
 
 --prune-empty::
 	Some kind of filters will generate empty commits, that left the tree
diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index 3890c22..be36db4 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -125,6 +125,7 @@ filter_subdir=
 orig_namespace=refs/original/
 force=
 prune_empty=
+remap_to_ancestor=
 while :
 do
 	case "$1" in
@@ -137,6 +138,11 @@ do
 		force=t
 		continue
 		;;
+	--remap-to-ancestor)
+		shift
+		remap_to_ancestor=t
+		continue
+		;;
 	--prune-empty)
 		shift
 		prune_empty=t
@@ -182,6 +188,7 @@ do
 		;;
 	--subdirectory-filter)
 		filter_subdir="$OPTARG"
+		remap_to_ancestor=t
 		;;
 	--original)
 		orig_namespace=$(expr "$OPTARG/" : '\(.*[^/]\)/*$')/
@@ -364,7 +371,7 @@ done <../revs
 # revision walker.  Fix it by mapping these heads to the unique nearest
 # ancestor that survived the pruning.
 
-if test "$filter_subdir"
+if test "$remap_to_ancestor" = t
 then
 	while read ref
 	do
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index 329c851..9503875 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -288,4 +288,22 @@ test_expect_success 'Prune empty commits' '
 	test_cmp expect actual
 '
 
+test_expect_success '--remap-to-ancestor with filename filters' '
+	git checkout master &&
+	git reset --hard A &&
+	test_commit add-foo foo 1 &&
+	git branch moved-foo &&
+	test_commit add-bar bar a &&
+	git branch invariant &&
+	orig_invariant=$(git rev-parse invariant) &&
+	git branch moved-bar &&
+	test_commit change-foo foo 2 &&
+	git filter-branch -f --remap-to-ancestor \
+		moved-foo moved-bar A..master \
+		-- -- foo &&
+	test $(git rev-parse moved-foo) = $(git rev-parse moved-bar) &&
+	test $(git rev-parse moved-foo) = $(git rev-parse master^) &&
+	test $orig_invariant = $(git rev-parse invariant)
+'
+
 test_done
-- 
1.6.5.1.142.g4bac9
Previous: Thomas RastNext: Johannes Sixt
Message 4 of 22 in “filter-branch: stop special-casing $filter_subdir argument”
  1. 1/2 filter-branch: stop special-casing $filter_subdir argumentThomas Rast, Oct 21, 2009
  2. 2/2 filter-branch: nearest-ancestor rewriting outside subdir filterThomas Rast, Oct 21, 2009
  3. 1/2 filter-branch: stop special-casing $filter_subdir argumentThomas Rast, Oct 21, 2009
  4. 2/2 filter-branch: nearest-ancestor rewriting outside subdir filterThomas Rast, Oct 21, 2009
  5. Johannes SixtOct 22, 2009
  6. Thomas RastOct 22, 2009
  7. Johannes SixtOct 22, 2009
  8. 1/2 filter-branch: stop special-casing $filter_subdir argumentThomas Rast, Oct 28, 2009
  9. 2/2 filter-branch: nearest-ancestor rewriting outside subdir filterThomas Rast, Oct 28, 2009
  10. Johannes SixtOct 29, 2009
  11. Johannes SixtOct 29, 2009
  12. 1/2 filter-branch: stop special-casing $filter_subdir argumentThomas Rast, Nov 10, 2009
  13. 2/2 filter-branch: nearest-ancestor rewriting outside subdir filterThomas Rast, Nov 10, 2009
  14. Johannes SixtNov 11, 2009
  15. 1/2 filter-branch: stop special-casing $filter_subdir argumentJohannes Sixt, Nov 11, 2009
  16. 2/2 filter-branch: nearest-ancestor rewriting outside subdir filterJohannes Sixt, Nov 11, 2009
  17. Junio C HamanoNov 11, 2009
  18. Thomas RastNov 11, 2009
  19. Johannes SixtNov 11, 2009
  20. Thomas RastNov 11, 2009
  21. Johannes SixtNov 11, 2009
  22. Junio C HamanoNov 11, 2009

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.