git/list[1] front-page[2] threads[3] people[4] search[5] about
 

BUG: git filter-branch does not make tree replacements permanent

From
Robert Luberda <robert@debian.org>
Date
Apr 11, 2013, 21:08 UTC
Message-ID
<20130411210816.GA15810@vox.robbo.home>
Hi,
The git filter-branch man page states:
  NOTE: This command honors .git/info/grafts and .git/refs/replace/. 
        If you have any grafts or replacement refs defined, running 
        this command will make them permanent.

However the command does not seem to honor tree (or blob) objects replacements. The bug can be reproduced (with both git 1.7.10 and 1.8.2.1.342.gfa7285d) in the following simple steps:

1. Setup:
	git init
	for i in a b c d; do echo $i >> f; git add f; git commit -m "$i"; done
	git diff HEAD~2..HEAD~1  # the output is non-empty
2. Add replacement for some tree object
	git replace `git log --format=raw | sed -ne 's/^tree //p' | sed -n 2,3p | tac`
	git diff HEAD~2..HEAD~1  # the output is now empty
3. Run filter-branch:
	git filter-branch
4. Verify that unfortunatelly it did nothing:
	git replace | xargs git replace -d
	git diff HEAD~2..HEAD~1  # the output is still not empty

The following work-around works for me for tree objects replacements, but I don't think it is suitable for inclusion in git sources. Most probably git write-tree should be changed instead to take both the blob and tree replacements into account.

 
diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index ac2a005..68064f2 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -276,6 +276,16 @@ test $commits -eq 0 && die "Found nothing to rewrite"
 
 # Rewrite the commits
 
+write_tree_func()
+{
+ m="$(git write-tree "$@")"
+ if [ -e "$ORIG_GIT_DIR/refs/replace/$m" ] ; then
+   n="$(cat "$ORIG_GIT_DIR/refs/replace/$m")"
+   echo "Replaced tree $m with $n" >&2
+   m="$n"
+ fi
+ echo "$m"
+}
 git_filter_branch__commit_count=0
 while read commit parents; do
 	git_filter_branch__commit_count=$(($git_filter_branch__commit_count+1))
@@ -342,8 +352,8 @@ while read commit parents; do
 	sed -e '1,/^$/d' <../commit | \
 		eval "$filter_msg" > ../message ||
 			die "msg filter failed: $filter_msg"
-	workdir=$workdir @SHELL_PATH@ -c "$filter_commit" "git commit-tree" \
-		$(git write-tree) $parentstr < ../message > ../map/$commit ||
+	workdir=$workdir /bin/sh -c "$filter_commit" "git commit-tree" \
+		$(write_tree_func) $parentstr < ../message > ../map/$commit ||
 			die "could not write rewritten commit"
 done <../revs

Regards,
robert
 
Message 1 of 1 in “BUG: git filter-branch does not make tree replacements permanent”
  1. Robert LuberdaApr 11, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.