@matheusbsbs / matheus-bagliano / commits / f2f3a6b802
Fork 0

filter-branch: nearest-ancestor rewriting outside subdir filter

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> Signed-off-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Thomas Rast committed Nov 10, 2009 at 22:04 UTC f2f3a6b802e3dae09a1c414cd8516ff2a546a527
3 files changed +43 -6
Documentation/git-filter-branch.txt
+12 -1
@@ -159,7 +159,18 @@ to other tags will be rewritten to point to the underlying commit.
159 --subdirectory-filter <directory>::
160 Only look at the history which touches the given subdirectory.
161 The result will contain that directory (and only that) as its
162 - project root.
162 + project root. Implies --remap-to-ancestor.
163 +
164 +--remap-to-ancestor::
165 + Rewrite refs to the nearest rewritten ancestor instead of
166 + ignoring them.
167 ++
168 +Normally, positive refs on the command line are only changed if the
169 +commit they point to was rewritten. However, you can limit the extent
170 +of this rewriting by using linkgit:rev-list[1] arguments, e.g., path
171 +limiters. Refs pointing to such excluded commits would then normally
172 +be ignored. With this option, they are instead rewritten to point at
173 +the nearest ancestor that was not excluded.
174
175 --prune-empty::
176 Some kind of filters will generate empty commits, that left the tree
git-filter-branch.sh
+13 -5
@@ -125,6 +125,7 @@ filter_subdir=
125 orig_namespace=refs/original/
126 force=
127 prune_empty=
128 +remap_to_ancestor=
129 while :
130 do
131 case "$1" in
@@ -137,6 +138,11 @@ do
138 force=t
139 continue
140 ;;
141 + --remap-to-ancestor)
142 + shift
143 + remap_to_ancestor=t
144 + continue
145 + ;;
146 --prune-empty)
147 shift
148 prune_empty=t
@@ -182,6 +188,7 @@ do
188 ;;
189 --subdirectory-filter)
190 filter_subdir="$OPTARG"
191 + remap_to_ancestor=t
192 ;;
193 --original)
194 orig_namespace=$(expr "$OPTARG/" : '\(.*[^/]\)/*$')/
@@ -354,12 +361,13 @@ while read commit parents; do
361 die "could not write rewritten commit"
362 done <../revs
363
357 -# In case of a subdirectory filter, it is possible that a specified head
358 -# is not in the set of rewritten commits, because it was pruned by the
359 -# revision walker. Fix it by mapping these heads to the unique nearest
360 -# ancestor that survived the pruning.
364 +# If we are filtering for paths, as in the case of a subdirectory
365 +# filter, it is possible that a specified head is not in the set of
366 +# rewritten commits, because it was pruned by the revision walker.
367 +# Ancestor remapping fixes this by mapping these heads to the unique
368 +# nearest ancestor that survived the pruning.
369
362 -if test "$filter_subdir"
370 +if test "$remap_to_ancestor" = t
371 then
372 while read ref
373 do
t/t7003-filter-branch.sh
+18
@@ -288,4 +288,22 @@ test_expect_success 'Prune empty commits' '
288 test_cmp expect actual
289 '
290
291 +test_expect_success '--remap-to-ancestor with filename filters' '
292 + git checkout master &&
293 + git reset --hard A &&
294 + test_commit add-foo foo 1 &&
295 + git branch moved-foo &&
296 + test_commit add-bar bar a &&
297 + git branch invariant &&
298 + orig_invariant=$(git rev-parse invariant) &&
299 + git branch moved-bar &&
300 + test_commit change-foo foo 2 &&
301 + git filter-branch -f --remap-to-ancestor \
302 + moved-foo moved-bar A..master \
303 + -- -- foo &&
304 + test $(git rev-parse moved-foo) = $(git rev-parse moved-bar) &&
305 + test $(git rev-parse moved-foo) = $(git rev-parse master^) &&
306 + test $orig_invariant = $(git rev-parse invariant)
307 +'
308 +
309 test_done