Skip to content

Commit e0e7cb8

Browse files
t-bgitster
authored andcommitted
log -G: ignore binary files
The -G<regex> option of log looks for the differences whose patch text contains added/removed lines that match regex. Currently -G looks also into patches of binary files (which according to [1]) is binary as well. This has a couple of issues: - It makes the pickaxe search slow. In a proprietary repository of the author with only ~5500 commits and a total .git size of ~300MB searching takes ~13 seconds $time git log -Gwave > /dev/null real 0m13,241s user 0m12,596s sys 0m0,644s whereas when we ignore binary files with this patch it takes ~4s $time ~/devel/git/git log -Gwave > /dev/null real 0m3,713s user 0m3,608s sys 0m0,105s which is a speedup of more than fourfold. - The internally used algorithm for generating patch text is based on xdiff and its states in [1] > The output format of the binary patch file is proprietary > (and binary) and it is basically a collection of copy and insert > commands [..] which means that the current format could change once the internal algorithm is changed as the format is not standardized. In addition the git binary patch format used for preparing patches for git apply is *different* from the xdiff format as can be seen by comparing git log -p -a commit 6e95bf4bafccf14650d02ab57f3affe669be10cf Author: A U Thor <[email protected]> Date: Thu Apr 7 15:14:13 2005 -0700 modify binary file diff --git a/data.bin b/data.bin index f414c84..edfeb6f 100644 --- a/data.bin +++ b/data.bin @@ -1,2 +1,4 @@ a a^@A +a +a^@A with git log --binary commit 6e95bf4bafccf14650d02ab57f3affe669be10cf Author: A U Thor <[email protected]> Date: Thu Apr 7 15:14:13 2005 -0700 modify binary file diff --git a/data.bin b/data.bin index f414c84bd3aa25fa07836bb1fb73db784635e24b..edfeb6f501[..] GIT binary patch literal 12 QcmYe~N@Pgn0zx1O01)N^ZvX%Q literal 6 NcmYe~N@Pgn0ssWg0XP5v which seems unexpected. To resolve these issues this patch makes -G<regex> ignore binary files by default. Textconv filters are supported and also -a/--text for getting the old and broken behaviour back. The -S<block of text> option of log looks for differences that changes the number of occurrences of the specified block of text (i.e. addition/deletion) in a file. As we want to keep the current behaviour, add a test to ensure it stays that way. [1]: http://www.xmailserver.org/xdiff.html Signed-off-by: Thomas Braun <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent a159801 commit e0e7cb8

File tree

4 files changed

+48
-1
lines changed

4 files changed

+48
-1
lines changed

Documentation/diff-options.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,8 @@ struct), and want to know the history of that block since it first
524524
came into being: use the feature iteratively to feed the interesting
525525
block in the preimage back into `-S`, and keep going until you get the
526526
very first version of the block.
527+
+
528+
Binary files are searched as well.
527529

528530
-G<regex>::
529531
Look for differences whose patch text contains added/removed
@@ -543,6 +545,9 @@ While `git log -G"regexec\(regexp"` will show this commit, `git log
543545
-S"regexec\(regexp" --pickaxe-regex` will not (because the number of
544546
occurrences of that string did not change).
545547
+
548+
Unless `--text` is supplied patches of binary files without a textconv
549+
filter will be ignored.
550+
+
546551
See the 'pickaxe' entry in linkgit:gitdiffcore[7] for more
547552
information.
548553

Documentation/gitdiffcore.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ textual diff has an added or a deleted line that matches the given
242242
regular expression. This means that it will detect in-file (or what
243243
rename-detection considers the same file) moves, which is noise. The
244244
implementation runs diff twice and greps, and this can be quite
245-
expensive.
245+
expensive. To speed things up binary files without textconv filters
246+
will be ignored.
246247

247248
When `-S` or `-G` are used without `--pickaxe-all`, only filepairs
248249
that match their respective criterion are kept in the output. When

diffcore-pickaxe.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ static int pickaxe_match(struct diff_filepair *p, struct diff_options *o,
154154
if (textconv_one == textconv_two && diff_unmodified_pair(p))
155155
return 0;
156156

157+
if ((o->pickaxe_opts & DIFF_PICKAXE_KIND_G) &&
158+
!o->flags.text &&
159+
((!textconv_one && diff_filespec_is_binary(o->repo, p->one)) ||
160+
(!textconv_two && diff_filespec_is_binary(o->repo, p->two))))
161+
return 0;
162+
157163
mf1.size = fill_textconv(o->repo, textconv_one, p->one, &mf1.ptr);
158164
mf2.size = fill_textconv(o->repo, textconv_two, p->two, &mf2.ptr);
159165

t/t4209-log-pickaxe.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,39 @@ test_expect_success 'log -S --no-textconv (missing textconv tool)' '
106106
rm .gitattributes
107107
'
108108

109+
test_expect_success 'setup log -[GS] binary & --text' '
110+
git checkout --orphan GS-binary-and-text &&
111+
git read-tree --empty &&
112+
printf "a\na\0a\n" >data.bin &&
113+
git add data.bin &&
114+
git commit -m "create binary file" data.bin &&
115+
printf "a\na\0a\n" >>data.bin &&
116+
git commit -m "modify binary file" data.bin &&
117+
git rm data.bin &&
118+
git commit -m "delete binary file" data.bin &&
119+
git log >full-log
120+
'
121+
122+
test_expect_success 'log -G ignores binary files' '
123+
git log -Ga >log &&
124+
test_must_be_empty log
125+
'
126+
127+
test_expect_success 'log -G looks into binary files with -a' '
128+
git log -a -Ga >log &&
129+
test_cmp log full-log
130+
'
131+
132+
test_expect_success 'log -G looks into binary files with textconv filter' '
133+
test_when_finished "rm .gitattributes" &&
134+
echo "* diff=bin" >.gitattributes &&
135+
git -c diff.bin.textconv=cat log -Ga >log &&
136+
test_cmp log full-log
137+
'
138+
139+
test_expect_success 'log -S looks into binary files' '
140+
git log -Sa >log &&
141+
test_cmp log full-log
142+
'
143+
109144
test_done

0 commit comments

Comments
 (0)