Skip to content

Commit

Permalink
filter-branch: avoid passing commit message through sed
Browse files Browse the repository at this point in the history
On some systems (like OS X), if sed encounters input without
a trailing newline, it will silently add it. As a result,
"git filter-branch" on such systems may silently rewrite
commit messages that omit a trailing newline. Even though
this is not something we generate ourselves with "git
commit", it's better for filter-branch to preserve the
original data as closely as possible.

We're using sed here only to strip the header fields from
the commit object. We can accomplish the same thing with a
shell loop. Since shell "read" calls are slow (usually one
syscall per byte), we use "cat" once we've skipped past the
header. Depending on the size of your commit messages, this
is probably faster (you pay the cost to fork, but then read
the data in saner-sized chunks). This idea is shamelessly
stolen from Junio.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jeff King authored and Junio C Hamano committed Apr 29, 2015
1 parent 282616c commit df06201
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 1 deletion.
10 changes: 9 additions & 1 deletion git-filter-branch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,15 @@ while read commit parents; do
die "parent filter failed: $filter_parent"
fi

sed -e '1,/^$/d' <../commit | \
{
while read -r header_line && test -n "$header_line"
do
# skip header lines...
:;
done
# and output the actual commit message
cat
} <../commit |
eval "$filter_msg" > ../message ||
die "msg filter failed: $filter_msg"
workdir=$workdir @SHELL_PATH@ -c "$filter_commit" "git commit-tree" \
Expand Down
10 changes: 10 additions & 0 deletions t/t7003-filter-branch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -394,4 +394,14 @@ test_expect_success 'replace submodule revision' '
test $orig_head != `git show-ref --hash --head HEAD`
'

test_expect_success 'filter commit message without trailing newline' '
git reset --hard original &&
commit=$(printf "no newline" | git commit-tree HEAD^{tree}) &&
git update-ref refs/heads/no-newline $commit &&
git filter-branch -f refs/heads/no-newline &&
echo $commit >expect &&
git rev-parse refs/heads/no-newline >actual &&
test_cmp expect actual
'

test_done

0 comments on commit df06201

Please sign in to comment.