The first thing filter-branch does is to create a temporary
directory, either ".git-rewrite" in the current directory
(which may be the working tree or the repository if bare),
or in a directory specified by "-d". We then chdir to
$tempdir/t as our temporary working directory in which to run
tree filters.

After finishing the filter, we then attempt to go back to
the original directory with "cd ../..". This works in the
.git-rewrite case, but if "-d" is used, we end up in a
random directory. The only thing we do after this chdir is
to run git-read-tree, but that means that:

  1. The working directory is not updated to reflect the
     filtered history.

  2. We dump random files into "$tempdir/.." (e.g., if you
     use "-d /tmp/foo", we dump junk into /tmp).

Fix it by recording the full path to the original directory
and returning there explicitly.

Signed-off-by: Jeff King <>
On Tue, Apr 02, 2013 at 02:32:21PM +0200, Martin Erik Werner wrote:

> I think I have stumbled on a bug in the -d option of git filter-branch.
> It seems like in the final stage of filter-branch, regardless of where
> -d is set, it will make updates to the "working directory" as being the
> parent of the -d directory, and the actual working directory is left as
> it were before the filtering.

Yep, definitely a bug. Thanks for reporting.     |  5 +++--
 t/ | 14 ++++++++++++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/ b/
index 5314249..ac2a005 100755
--- a/
+++ b/
@@ -199,6 +199,7 @@ esac
        test -d "$tempdir" &&
                die "$tempdir already exists, please remove it"
 mkdir -p "$tempdir/t" &&
 tempdir="$(cd "$tempdir"; pwd)" &&
 cd "$tempdir/t" &&
@@ -206,7 +207,7 @@ die ""
 die ""
 # Remove tempdir on exit
-trap 'cd ../..; rm -rf "$tempdir"' 0
+trap 'cd "$orig_dir"; rm -rf "$tempdir"' 0
@@ -469,7 +470,7 @@ fi
-cd ../..
+cd "$orig_dir"
 rm -rf "$tempdir"
 trap - 0
diff --git a/t/ b/t/
index 1e7a209..9496736 100755
--- a/t/
+++ b/t/
@@ -64,6 +64,20 @@ test_expect_success 'correct GIT_DIR while using -d' '
        grep drepo "$TRASHDIR/backup-refs"
+test_expect_success 'tree-filter works with -d' '
+       git init drepo-tree &&
+       (
+               cd drepo-tree &&
+               test_commit one &&
+               git filter-branch -d "$TRASHDIR/dfoo" \
+                       --tree-filter "echo changed >one.t" &&
+               echo changed >expect &&
+               git cat-file blob HEAD:one.t >actual &&
+               test_cmp expect actual &&
+               test_cmp one.t actual
+       )
 test_expect_success 'Fail if commit filter fails' '
        test_must_fail git filter-branch -f --commit-filter "exit 1" HEAD

To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to
More majordomo info at

Reply via email to