Teach filter-branch about subdirectory filtering
With git-filter-branch --subdirectory-filter <subdirectory> you can get at the history, as seen by a certain subdirectory. The history of the rewritten branch will only contain commits that touched that subdirectory, and the subdirectory will be rewritten to be the new project root. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
3520e1e868
commit
685ef546b6
@ -119,6 +119,10 @@
|
|||||||
# attached, the rewritten tag won't have it. Sorry. (It is by
|
# attached, the rewritten tag won't have it. Sorry. (It is by
|
||||||
# definition impossible to preserve signatures at any rate, though.)
|
# definition impossible to preserve signatures at any rate, though.)
|
||||||
#
|
#
|
||||||
|
# --subdirectory-filter DIRECTORY:: Only regard the history, as seen by
|
||||||
|
# the given subdirectory. The result will contain that directory as
|
||||||
|
# its project root.
|
||||||
|
#
|
||||||
# EXAMPLE USAGE
|
# EXAMPLE USAGE
|
||||||
# -------------
|
# -------------
|
||||||
# Suppose you want to remove a file (containing confidential information
|
# Suppose you want to remove a file (containing confidential information
|
||||||
@ -224,7 +228,13 @@ set_ident () {
|
|||||||
|
|
||||||
# list all parent's object names for a given commit
|
# list all parent's object names for a given commit
|
||||||
get_parents () {
|
get_parents () {
|
||||||
git-rev-list -1 --parents "$1" | sed "s/^[0-9a-f]*//"
|
case "$filter_subdir" in
|
||||||
|
"")
|
||||||
|
git-rev-list -1 --parents "$1"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
git-rev-list -1 --parents "$1" -- "$filter_subdir"
|
||||||
|
esac | sed "s/^[0-9a-f]*//"
|
||||||
}
|
}
|
||||||
|
|
||||||
tempdir=.git-rewrite
|
tempdir=.git-rewrite
|
||||||
@ -235,6 +245,7 @@ filter_parent=
|
|||||||
filter_msg=cat
|
filter_msg=cat
|
||||||
filter_commit='git-commit-tree "$@"'
|
filter_commit='git-commit-tree "$@"'
|
||||||
filter_tag_name=
|
filter_tag_name=
|
||||||
|
filter_subdir=
|
||||||
while case "$#" in 0) usage;; esac
|
while case "$#" in 0) usage;; esac
|
||||||
do
|
do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
@ -280,6 +291,9 @@ do
|
|||||||
--tag-name-filter)
|
--tag-name-filter)
|
||||||
filter_tag_name="$OPTARG"
|
filter_tag_name="$OPTARG"
|
||||||
;;
|
;;
|
||||||
|
--subdirectory-filter)
|
||||||
|
filter_subdir="$OPTARG"
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
usage
|
usage
|
||||||
;;
|
;;
|
||||||
@ -313,7 +327,14 @@ ret=0
|
|||||||
|
|
||||||
mkdir ../map # map old->new commit ids for rewriting parents
|
mkdir ../map # map old->new commit ids for rewriting parents
|
||||||
|
|
||||||
git-rev-list --reverse --topo-order --default HEAD "$@" >../revs
|
case "$filter_subdir" in
|
||||||
|
"")
|
||||||
|
git-rev-list --reverse --topo-order --default HEAD "$@"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
git-rev-list --reverse --topo-order --default HEAD "$@" \
|
||||||
|
-- "$filter_subdir"
|
||||||
|
esac > ../revs
|
||||||
commits=$(cat ../revs | wc -l | tr -d " ")
|
commits=$(cat ../revs | wc -l | tr -d " ")
|
||||||
|
|
||||||
test $commits -eq 0 && die "Found nothing to rewrite"
|
test $commits -eq 0 && die "Found nothing to rewrite"
|
||||||
@ -323,7 +344,13 @@ while read commit; do
|
|||||||
i=$(($i+1))
|
i=$(($i+1))
|
||||||
printf "$commit ($i/$commits) "
|
printf "$commit ($i/$commits) "
|
||||||
|
|
||||||
git-read-tree -i -m $commit
|
case "$filter_subdir" in
|
||||||
|
"")
|
||||||
|
git-read-tree -i -m $commit
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
git-read-tree -i -m $commit:"$filter_subdir"
|
||||||
|
esac
|
||||||
|
|
||||||
export GIT_COMMIT=$commit
|
export GIT_COMMIT=$commit
|
||||||
git-cat-file commit "$commit" >../commit
|
git-cat-file commit "$commit" >../commit
|
||||||
|
@ -54,4 +54,28 @@ test_expect_success 'common ancestor is still common (unchanged)' '
|
|||||||
test "$(git-merge-base modD D)" = "$(git-rev-parse B)"
|
test "$(git-merge-base modD D)" = "$(git-rev-parse B)"
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'filter subdirectory only' '
|
||||||
|
mkdir subdir &&
|
||||||
|
touch subdir/new &&
|
||||||
|
git add subdir/new &&
|
||||||
|
test_tick &&
|
||||||
|
git commit -m "subdir" &&
|
||||||
|
echo H > a &&
|
||||||
|
test_tick &&
|
||||||
|
git commit -m "not subdir" a &&
|
||||||
|
echo A > subdir/new &&
|
||||||
|
test_tick &&
|
||||||
|
git commit -m "again subdir" subdir/new &&
|
||||||
|
git rm a &&
|
||||||
|
test_tick &&
|
||||||
|
git commit -m "again not subdir" &&
|
||||||
|
git-filter-branch --subdirectory-filter subdir sub
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'subdirectory filter result looks okay' '
|
||||||
|
test 2 = $(git-rev-list sub | wc -l) &&
|
||||||
|
git show sub:new &&
|
||||||
|
! git show sub:subdir
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Reference in New Issue
Block a user