{"thread":{"id":"33351","subject":"Bug in filter-branch -d option, new files are dumped into parent","startedAt":"2013-04-02T12:32:21Z","lastAt":"2013-04-02T14:22:19Z","messageCount":2,"participants":["Martin Erik Werner","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"212875","messageId":"1364905941.19800.24.camel@mas","threadId":"33351","inReplyTo":null,"subject":"Bug in filter-branch -d option, new files are dumped into parent","fromName":"Martin Erik Werner","fromEmail":"martinerikwerner@gmail.com","sentAt":"2013-04-02T12:32:21Z","receivedAt":"2013-04-02T12:32:21Z","isPatch":false,"sender":{"key":"martinerikwerner@gmail.com","avatar":"https://avatars.githubusercontent.com/u/732190?v=4"},"body":"Hi,\nI think I have stumbled on a bug in the -d option of git filter-branch.\n\nIt seems like in the final stage of filter-branch, regardless of where\n-d is set, it will make updates to the \"working directory\" as being the\nparent of the -d directory, and the actual working directory is left as\nit were before the filtering.\n\nFor example if using -d /tmp/git-rewrite, the new checkout files are\ndumped into /tmp.\n\nA simple test scenario:\n\n###\nmkdir test\ncd test\ngit init\n\necho foo >foo\ngit add foo\ngit commit -m\"foo\"\necho bar >bar\ngit add bar\ngit commit -m\"bar\"\n\ngit checkout -b rewrite\ngit filter-branch -d /tmp/git-rewrite --tree-filter 'echo baz >baz' --\nrewrite\n# git status\n# shows 'baz' as unstaged-deleted in the working directory\n#\n# ls /tmp/\n# shows the 'baz' file created in the root, above git-rewrite\n#\n# git log --stat --oneline\n# does show expected result though\n#\n# if you run it again you'll get an error because of the /tmp/baz file\ngit reset --hard master\ngit filter-branch -f -d /tmp/git-rewrite --tree-filter 'echo baz >baz'\n-- rewrite\n# Rewrite afac18542ac3d432b647866f5ac6918b81b3bb78 (2/2)\n# Ref 'refs/heads/rewrite' was rewritten\n# error: Untracked working tree file 'baz' would be overwritten by\nmerge.\n#\n# At this point, 'baz' is instead staged-deleted in the working\ndirectory\n###\n\n-- \nMartin Erik Werner <martinerikwerner@gmail.com>\n"},{"id":"212879","messageId":"20130402142219.GB23828@sigill.intra.peff.net","threadId":"33351","inReplyTo":"1364905941.19800.24.camel@mas","subject":"[PATCH] filter-branch: return to original dir after filtering","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2013-04-02T14:22:19Z","receivedAt":"2013-04-02T14:22:19Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"The first thing filter-branch does is to create a temporary\ndirectory, either \".git-rewrite\" in the current directory\n(which may be the working tree or the repository if bare),\nor in a directory specified by \"-d\". We then chdir to\n$tempdir/t as our temporary working directory in which to run\ntree filters.\n\nAfter finishing the filter, we then attempt to go back to\nthe original directory with \"cd ../..\". This works in the\n.git-rewrite case, but if \"-d\" is used, we end up in a\nrandom directory. The only thing we do after this chdir is\nto run git-read-tree, but that means that:\n\n  1. The working directory is not updated to reflect the\n     filtered history.\n\n  2. We dump random files into \"$tempdir/..\" (e.g., if you\n     use \"-d /tmp/foo\", we dump junk into /tmp).\n\nFix it by recording the full path to the original directory\nand returning there explicitly.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nOn Tue, Apr 02, 2013 at 02:32:21PM +0200, Martin Erik Werner wrote:\n\n> I think I have stumbled on a bug in the -d option of git filter-branch.\n> \n> It seems like in the final stage of filter-branch, regardless of where\n> -d is set, it will make updates to the \"working directory\" as being the\n> parent of the -d directory, and the actual working directory is left as\n> it were before the filtering.\n\nYep, definitely a bug. Thanks for reporting.\n\n git-filter-branch.sh     |  5 +++--\n t/t7003-filter-branch.sh | 14 ++++++++++++++\n 2 files changed, 17 insertions(+), 2 deletions(-)\n\ndiff --git a/git-filter-branch.sh b/git-filter-branch.sh\nindex 5314249..ac2a005 100755\n--- a/git-filter-branch.sh\n+++ b/git-filter-branch.sh\n@@ -199,6 +199,7 @@ esac\n \ttest -d \"$tempdir\" &&\n \t\tdie \"$tempdir already exists, please remove it\"\n esac\n+orig_dir=$(pwd)\n mkdir -p \"$tempdir/t\" &&\n tempdir=\"$(cd \"$tempdir\"; pwd)\" &&\n cd \"$tempdir/t\" &&\n@@ -206,7 +207,7 @@ die \"\"\n die \"\"\n \n # Remove tempdir on exit\n-trap 'cd ../..; rm -rf \"$tempdir\"' 0\n+trap 'cd \"$orig_dir\"; rm -rf \"$tempdir\"' 0\n \n ORIG_GIT_DIR=\"$GIT_DIR\"\n ORIG_GIT_WORK_TREE=\"$GIT_WORK_TREE\"\n@@ -469,7 +470,7 @@ fi\n \tdone\n fi\n \n-cd ../..\n+cd \"$orig_dir\"\n rm -rf \"$tempdir\"\n \n trap - 0\ndiff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh\nindex 1e7a209..9496736 100755\n--- a/t/t7003-filter-branch.sh\n+++ b/t/t7003-filter-branch.sh\n@@ -64,6 +64,20 @@ test_expect_success 'correct GIT_DIR while using -d' '\n \tgrep drepo \"$TRASHDIR/backup-refs\"\n '\n \n+test_expect_success 'tree-filter works with -d' '\n+\tgit init drepo-tree &&\n+\t(\n+\t\tcd drepo-tree &&\n+\t\ttest_commit one &&\n+\t\tgit filter-branch -d \"$TRASHDIR/dfoo\" \\\n+\t\t\t--tree-filter \"echo changed >one.t\" &&\n+\t\techo changed >expect &&\n+\t\tgit cat-file blob HEAD:one.t >actual &&\n+\t\ttest_cmp expect actual &&\n+\t\ttest_cmp one.t actual\n+\t)\n+'\n+\n test_expect_success 'Fail if commit filter fails' '\n \ttest_must_fail git filter-branch -f --commit-filter \"exit 1\" HEAD\n '\n-- \n1.8.2.rc0.33.gd915649\n"}]}