{"thread":{"id":"33484","subject":"BUG: git filter-branch does not make tree replacements permanent","startedAt":"2013-04-11T21:08:16Z","lastAt":"2013-04-11T21:08:16Z","messageCount":1,"participants":["Robert Luberda"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"214009","messageId":"20130411210816.GA15810@vox.robbo.home","threadId":"33484","inReplyTo":null,"subject":"BUG: git filter-branch does not make tree replacements permanent","fromName":"Robert Luberda","fromEmail":"robert@debian.org","sentAt":"2013-04-11T21:08:16Z","receivedAt":"2013-04-11T21:08:16Z","isPatch":false,"sender":{"key":"robert@debian.org","avatar":"https://avatars.githubusercontent.com/u/18017362?v=4"},"body":"\nHi,\n\nThe git filter-branch man page states:\n\n  NOTE: This command honors .git/info/grafts and .git/refs/replace/. \n        If you have any grafts or replacement refs defined, running \n        this command will make them permanent.\n\nHowever the command  does not seem to honor tree (or blob) objects\nreplacements. The bug can be reproduced (with both git 1.7.10 and \n1.8.2.1.342.gfa7285d) in the following simple steps:\n\n\n1. Setup:\n\tgit init\n\tfor i in a b c d; do echo $i >> f; git add f; git commit -m \"$i\"; done\n\tgit diff HEAD~2..HEAD~1  # the output is non-empty\n2. Add replacement for some tree object\n\tgit replace `git log --format=raw | sed -ne 's/^tree //p' | sed -n 2,3p | tac`\n\tgit diff HEAD~2..HEAD~1  # the output is now empty\n3. Run filter-branch:\n\tgit filter-branch\n4. Verify that unfortunatelly it did nothing:\n\tgit replace | xargs git replace -d\n\tgit diff HEAD~2..HEAD~1  # the output is still not empty\n\n\n\nThe following work-around works for me for tree objects replacements,\nbut I don't think it is suitable for inclusion in git sources. Most\nprobably git write-tree should be changed instead to take both the blob\nand tree replacements into account.\n\n \ndiff --git a/git-filter-branch.sh b/git-filter-branch.sh\nindex ac2a005..68064f2 100755\n--- a/git-filter-branch.sh\n+++ b/git-filter-branch.sh\n@@ -276,6 +276,16 @@ test $commits -eq 0 && die \"Found nothing to rewrite\"\n \n # Rewrite the commits\n \n+write_tree_func()\n+{\n+ m=\"$(git write-tree \"$@\")\"\n+ if [ -e \"$ORIG_GIT_DIR/refs/replace/$m\" ] ; then\n+   n=\"$(cat \"$ORIG_GIT_DIR/refs/replace/$m\")\"\n+   echo \"Replaced tree $m with $n\" >&2\n+   m=\"$n\"\n+ fi\n+ echo \"$m\"\n+}\n git_filter_branch__commit_count=0\n while read commit parents; do\n \tgit_filter_branch__commit_count=$(($git_filter_branch__commit_count+1))\n@@ -342,8 +352,8 @@ while read commit parents; do\n \tsed -e '1,/^$/d' <../commit | \\\n \t\teval \"$filter_msg\" > ../message ||\n \t\t\tdie \"msg filter failed: $filter_msg\"\n-\tworkdir=$workdir @SHELL_PATH@ -c \"$filter_commit\" \"git commit-tree\" \\\n-\t\t$(git write-tree) $parentstr < ../message > ../map/$commit ||\n+\tworkdir=$workdir /bin/sh -c \"$filter_commit\" \"git commit-tree\" \\\n+\t\t$(write_tree_func) $parentstr < ../message > ../map/$commit ||\n \t\t\tdie \"could not write rewritten commit\"\n done <../revs\n\nRegards,\nrobert\n \n"}]}