From 685ef546b62d063c72b401cd38b83a879301aac4 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 8 Jun 2007 01:30:35 +0100 Subject: [PATCH] Teach filter-branch about subdirectory filtering With git-filter-branch --subdirectory-filter 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 Signed-off-by: Junio C Hamano --- git-filter-branch.sh | 33 ++++++++++++++++++++++++++++++--- t/t7003-filter-branch.sh | 24 ++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/git-filter-branch.sh b/git-filter-branch.sh index 9d61b7fff6..efb8f2dbca 100755 --- a/git-filter-branch.sh +++ b/git-filter-branch.sh @@ -119,6 +119,10 @@ # attached, the rewritten tag won't have it. Sorry. (It is by # 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 # ------------- # 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 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 @@ -235,6 +245,7 @@ filter_parent= filter_msg=cat filter_commit='git-commit-tree "$@"' filter_tag_name= +filter_subdir= while case "$#" in 0) usage;; esac do case "$1" in @@ -280,6 +291,9 @@ do --tag-name-filter) filter_tag_name="$OPTARG" ;; + --subdirectory-filter) + filter_subdir="$OPTARG" + ;; *) usage ;; @@ -313,7 +327,14 @@ ret=0 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 " ") test $commits -eq 0 && die "Found nothing to rewrite" @@ -323,7 +344,13 @@ while read commit; do i=$(($i+1)) 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 git-cat-file commit "$commit" >../commit diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh index 3739cb191d..292b83766d 100755 --- a/t/t7003-filter-branch.sh +++ b/t/t7003-filter-branch.sh @@ -54,4 +54,28 @@ test_expect_success 'common ancestor is still common (unchanged)' ' 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 -- 2.11.4.GIT