Skip to content

Commit 685ef54

Browse files
dschogitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 3520e1e commit 685ef54

File tree

2 files changed

+54
-3
lines changed

2 files changed

+54
-3
lines changed

git-filter-branch.sh

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@
119119
# attached, the rewritten tag won't have it. Sorry. (It is by
120120
# definition impossible to preserve signatures at any rate, though.)
121121
#
122+
# --subdirectory-filter DIRECTORY:: Only regard the history, as seen by
123+
# the given subdirectory. The result will contain that directory as
124+
# its project root.
125+
#
122126
# EXAMPLE USAGE
123127
# -------------
124128
# Suppose you want to remove a file (containing confidential information
@@ -224,7 +228,13 @@ set_ident () {
224228

225229
# list all parent's object names for a given commit
226230
get_parents () {
227-
git-rev-list -1 --parents "$1" | sed "s/^[0-9a-f]*//"
231+
case "$filter_subdir" in
232+
"")
233+
git-rev-list -1 --parents "$1"
234+
;;
235+
*)
236+
git-rev-list -1 --parents "$1" -- "$filter_subdir"
237+
esac | sed "s/^[0-9a-f]*//"
228238
}
229239

230240
tempdir=.git-rewrite
@@ -235,6 +245,7 @@ filter_parent=
235245
filter_msg=cat
236246
filter_commit='git-commit-tree "$@"'
237247
filter_tag_name=
248+
filter_subdir=
238249
while case "$#" in 0) usage;; esac
239250
do
240251
case "$1" in
@@ -280,6 +291,9 @@ do
280291
--tag-name-filter)
281292
filter_tag_name="$OPTARG"
282293
;;
294+
--subdirectory-filter)
295+
filter_subdir="$OPTARG"
296+
;;
283297
*)
284298
usage
285299
;;
@@ -313,7 +327,14 @@ ret=0
313327

314328
mkdir ../map # map old->new commit ids for rewriting parents
315329

316-
git-rev-list --reverse --topo-order --default HEAD "$@" >../revs
330+
case "$filter_subdir" in
331+
"")
332+
git-rev-list --reverse --topo-order --default HEAD "$@"
333+
;;
334+
*)
335+
git-rev-list --reverse --topo-order --default HEAD "$@" \
336+
-- "$filter_subdir"
337+
esac > ../revs
317338
commits=$(cat ../revs | wc -l | tr -d " ")
318339

319340
test $commits -eq 0 && die "Found nothing to rewrite"
@@ -323,7 +344,13 @@ while read commit; do
323344
i=$(($i+1))
324345
printf "$commit ($i/$commits) "
325346

326-
git-read-tree -i -m $commit
347+
case "$filter_subdir" in
348+
"")
349+
git-read-tree -i -m $commit
350+
;;
351+
*)
352+
git-read-tree -i -m $commit:"$filter_subdir"
353+
esac
327354

328355
export GIT_COMMIT=$commit
329356
git-cat-file commit "$commit" >../commit

t/t7003-filter-branch.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,28 @@ test_expect_success 'common ancestor is still common (unchanged)' '
5454
test "$(git-merge-base modD D)" = "$(git-rev-parse B)"
5555
'
5656

57+
test_expect_success 'filter subdirectory only' '
58+
mkdir subdir &&
59+
touch subdir/new &&
60+
git add subdir/new &&
61+
test_tick &&
62+
git commit -m "subdir" &&
63+
echo H > a &&
64+
test_tick &&
65+
git commit -m "not subdir" a &&
66+
echo A > subdir/new &&
67+
test_tick &&
68+
git commit -m "again subdir" subdir/new &&
69+
git rm a &&
70+
test_tick &&
71+
git commit -m "again not subdir" &&
72+
git-filter-branch --subdirectory-filter subdir sub
73+
'
74+
75+
test_expect_success 'subdirectory filter result looks okay' '
76+
test 2 = $(git-rev-list sub | wc -l) &&
77+
git show sub:new &&
78+
! git show sub:subdir
79+
'
80+
5781
test_done

0 commit comments

Comments
 (0)