summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2015-04-29 11:48:58 -0400
committerJunio C Hamano <gitster@pobox.com>2015-04-29 10:01:04 -0700
commitdf0620108b9710a06d5a2d9c125d43b97590cce6 (patch)
treee412b2280f96dee205ed20cb9c772d0477fb76f3
parent282616c72d1d08a77ca4fe1186cb708c38408d87 (diff)
downloadgit-df0620108b9710a06d5a2d9c125d43b97590cce6.tar.gz
filter-branch: avoid passing commit message through sed
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>
-rwxr-xr-xgit-filter-branch.sh10
-rwxr-xr-xt/t7003-filter-branch.sh10
2 files changed, 19 insertions, 1 deletions
diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index e6e99f5bb5..5b3f63d8bb 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -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" \
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index 66643e4bd7..855afda80a 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -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