Merge branch 'tr/filter-branch'

* tr/filter-branch:
  filter-branch: nearest-ancestor rewriting outside subdir filter
  filter-branch: stop special-casing $filter_subdir argument
This commit is contained in:
Junio C Hamano 2009-11-20 23:46:14 -08:00
commit aa437791d8
3 changed files with 58 additions and 13 deletions

View File

@ -159,7 +159,18 @@ to other tags will be rewritten to point to the underlying commit.
--subdirectory-filter <directory>:: --subdirectory-filter <directory>::
Only look at the history which touches the given subdirectory. Only look at the history which touches the given subdirectory.
The result will contain that directory (and only that) as its 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:: --prune-empty::
Some kind of filters will generate empty commits, that left the tree Some kind of filters will generate empty commits, that left the tree

View File

@ -125,6 +125,7 @@ filter_subdir=
orig_namespace=refs/original/ orig_namespace=refs/original/
force= force=
prune_empty= prune_empty=
remap_to_ancestor=
while : while :
do do
case "$1" in case "$1" in
@ -137,6 +138,11 @@ do
force=t force=t
continue continue
;; ;;
--remap-to-ancestor)
shift
remap_to_ancestor=t
continue
;;
--prune-empty) --prune-empty)
shift shift
prune_empty=t prune_empty=t
@ -182,6 +188,7 @@ do
;; ;;
--subdirectory-filter) --subdirectory-filter)
filter_subdir="$OPTARG" filter_subdir="$OPTARG"
remap_to_ancestor=t
;; ;;
--original) --original)
orig_namespace=$(expr "$OPTARG/" : '\(.*[^/]\)/*$')/ orig_namespace=$(expr "$OPTARG/" : '\(.*[^/]\)/*$')/
@ -257,15 +264,24 @@ git read-tree || die "Could not seed the index"
# map old->new commit ids for rewriting parents # map old->new commit ids for rewriting parents
mkdir ../map || die "Could not create map/ directory" mkdir ../map || die "Could not create map/ directory"
# we need "--" only if there are no path arguments in $@
nonrevs=$(git rev-parse --no-revs "$@") || exit
test -z "$nonrevs" && dashdash=-- || dashdash=
rev_args=$(git rev-parse --revs-only "$@")
case "$filter_subdir" in case "$filter_subdir" in
"") "")
git rev-list --reverse --topo-order --default HEAD \ eval set -- "$(git rev-parse --sq --no-revs "$@")"
--parents --simplify-merges "$@"
;; ;;
*) *)
git rev-list --reverse --topo-order --default HEAD \ eval set -- "$(git rev-parse --sq --no-revs "$@" $dashdash \
--parents --simplify-merges "$@" -- "$filter_subdir" "$filter_subdir")"
esac > ../revs || die "Could not get the commits" ;;
esac
git rev-list --reverse --topo-order --default HEAD \
--parents --simplify-merges $rev_args "$@" > ../revs ||
die "Could not get the commits"
commits=$(wc -l <../revs | tr -d " ") commits=$(wc -l <../revs | tr -d " ")
test $commits -eq 0 && die "Found nothing to rewrite" test $commits -eq 0 && die "Found nothing to rewrite"
@ -345,19 +361,19 @@ while read commit parents; do
die "could not write rewritten commit" die "could not write rewritten commit"
done <../revs done <../revs
# In case of a subdirectory filter, it is possible that a specified head # If we are filtering for paths, as in the case of a subdirectory
# is not in the set of rewritten commits, because it was pruned by the # filter, it is possible that a specified head is not in the set of
# revision walker. Fix it by mapping these heads to the unique nearest # rewritten commits, because it was pruned by the revision walker.
# ancestor that survived the pruning. # Ancestor remapping fixes this by mapping these heads to the unique
# nearest ancestor that survived the pruning.
if test "$filter_subdir" if test "$remap_to_ancestor" = t
then then
while read ref while read ref
do do
sha1=$(git rev-parse "$ref"^0) sha1=$(git rev-parse "$ref"^0)
test -f "$workdir"/../map/$sha1 && continue test -f "$workdir"/../map/$sha1 && continue
ancestor=$(git rev-list --simplify-merges -1 \ ancestor=$(git rev-list --simplify-merges -1 "$ref" "$@")
$ref -- "$filter_subdir")
test "$ancestor" && echo $(map $ancestor) >> "$workdir"/../map/$sha1 test "$ancestor" && echo $(map $ancestor) >> "$workdir"/../map/$sha1
done < "$tempdir"/heads done < "$tempdir"/heads
fi fi

View File

@ -288,4 +288,22 @@ test_expect_success 'Prune empty commits' '
test_cmp expect actual 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 test_done