From: Eric Raible <hidden> Date: 2016-06-15 22:47:00
[Surely this has been address before, but I wasn't able to find it...]
The documentation for git-log -S includes:
"Look for differences that introduce or remove an instance of <string>.
Note that this is different than the string simply appearing in diff output"
But I want to do that "different" thing (IOW I want search the diff output).
So must I loop through git-rev-list, grepping git-diff output on each commit?
Or if it _is_ possible to search the diff output directly then it
might be useful
to link to the relevant description instead of saying what -S doesn't do.
Thanks - Eric
The documentation for git-log -S includes:
"Look for differences that introduce or remove an instance of <string>.
Note that this is different than the string simply appearing in diff output"
But I want to do that "different" thing (IOW I want search the diff output).
So must I loop through git-rev-list, grepping git-diff output on each commit?
Currently, yes. There is no way to do it internally. A patch to
implement it would probably be accepted, though (see the thread I
mentioned above for more details).
You can at least combine rev-list and diff into one command, and grep
like this (for 'foo'):
git log -z -p | perl -0ne 'print if /^[-+].*foo/m' | tr '\0' '\n'
-Peff
From: Eric Raible <hidden> Date: 2016-06-15 22:47:00
On Mon, Jun 29, 2009 at 9:03 PM, Jeff King[off-list ref] wrote:
You can at least combine rev-list and diff into one command, and grep
like this (for 'foo'):
git log -z -p | perl -0ne 'print if /^[-+].*foo/m' | tr '\0' '\n'
-Peff
Thank you, that will do very nicely as a starting point.
What I _really_ want is the subset of all commits containing foo
who's oneline commit message doesn't match a given regexp.
So I'm used something like this to extract the commits of interest:
git log -z -p | perl -0ne 'print if /^[-+].*foo/m' | tr '\0' '\n' |
grep "^commit [0-9a-f]" | awk '{print $2}' |
xargs -n1 git log --pretty=oneline -1 |
grep -v dont_want
In this specific case of wanting to ignore particular commits a loop
over git-rev-list might yield a better solution. But the 'git-log | perl | tr'
snippet is a nice idiom for day-to-day use.
From: Jeff King <hidden> Date: 2016-06-15 22:47:00
On Tue, Jun 30, 2009 at 11:05:08AM -0700, Eric Raible wrote:
What I _really_ want is the subset of all commits containing foo
who's oneline commit message doesn't match a given regexp.
So I'm used something like this to extract the commits of interest:
git log -z -p | perl -0ne 'print if /^[-+].*foo/m' | tr '\0' '\n' |
grep "^commit [0-9a-f]" | awk '{print $2}' |
xargs -n1 git log --pretty=oneline -1 |
grep -v dont_want
I think you can do this a little more simply and efficiently as:
git log -z -p --format='GREP: %s' |
perl -0ne 'print if /^[-+].*foo/m && !/^GREP:.*dont_want/' |
tr '\0' '\n'
(though note that --format is new as of 1.6.3, I think; before that you
have to use "--pretty=format:"). Many fewer process invocations, and
less typing, though still easy to mess up. At one point I had considered
writing small wrapper scripts that understood the log output so you
could say:
git log -z -p | filter-author $A | filter-diff $D | filter-subject $S
which is nicely readable and Unix-y, but is really _slow_ compared to
git doing it all in a single process. I think a "--grep-subject" and a
"--grep-diff" (aka "--search") are the only things that are missing now,
and those would both be pretty easy to implement.
-Peff
From: Eric Raible <hidden> Date: 2016-06-15 22:47:00
On Tue, Jun 30, 2009 at 12:31 PM, Jeff King[off-list ref] wrote:
I think you can do this a little more simply and efficiently as:
git log -z -p --format='GREP: %s' |
perl -0ne 'print if /^[-+].*foo/m && !/^GREP:.*dont_want/' |
tr '\0' '\n'
(though note that --format is new as of 1.6.3, I think; before that you
have to use "--pretty=format:"). Many fewer process invocations, and
less typing, though still easy to mess up.
I agree that --format leads to a much prettier solution.
Unfortunately --format seems to turn off -z (at least in msysgit):
$ git --version
git version 1.6.3.2.1299.gee46c
$ git log -p > L1
$ git log -p -z > L2
$ diff L1 L2 | wc
2415 4347 62889
$ git log -p --format=%s > L1
$ git log -p -z --format=%s > L2
$ diff L1 L2 | wc
0 0 0
From: Eric Raible <hidden> Date: 2016-06-15 22:47:00
On Tue, Jun 30, 2009 at 2:22 PM, Eric Raible[off-list ref] wrote:
On Tue, Jun 30, 2009 at 12:31 PM, Jeff King[off-list ref] wrote:
quoted
I think you can do this a little more simply and efficiently as:
git log -z -p --format='GREP: %s' |
perl -0ne 'print if /^[-+].*foo/m && !/^GREP:.*dont_want/' |
tr '\0' '\n'
(though note that --format is new as of 1.6.3, I think; before that you
have to use "--pretty=format:"). Many fewer process invocations, and
less typing, though still easy to mess up.
I agree that --format leads to a much prettier solution.
Unfortunately --format seems to turn off -z (at least in msysgit):
Sorry to self-reply, but one obvious workaround is to encode the NULL
explicitly:
git log -z -p --format='%x00GREP: %s' | ...
Ugh. I did some looking into this. It actually does work if you do:
git log -p -z --pretty=format:%s
rather than
git log -p -z --pretty=tformat:%s
And --format=%s behaves as if 'tformat' was given. And if you are not up
to date on the difference, "format" implies "separator semantics", where
the NUL is placed _between_ each record. "tformat" implies "terminator
semantics", where the NUL is placed at the end.
Placing the separator correctly is fairly easy; when we start a new
record, if we are not the first, we print the separator. Placing a
terminator is a little trickier because of the way the code is
structured. I'll post my attempt in a minute; see patch 2/2 for more
discussion.
-Peff
From: Jeff King <hidden> Date: 2016-06-15 22:47:00
When using "git log -z" with --pretty=format's "separator"
semantics, we correctly insert a NUL between each record.
However, with "--pretty=tformat", we output no NULs at all,
whereas we should output one after each commit.
We can't just put a conditional in the code for the
"separator" case; that code is triggered at a completely
different time: when _starting_ a new commit, and we are not
the first commit to be shown. As opposed to termination
semantics, which means we must print the terminator at the
end of each commit.
Adding to the trickiness is that we must handle two cases:
with and without diff output. In fact, there is already a
spot (log-tree.c, ll. 442-445) which adds a hard-coded
newline as a terminator after the commit message. But we
can't just modify that to use the specified line terminator,
because sometimes it is acting as a separator between commit
message and diff, and sometimes it is acting as the
terminator of the whole record.
Simply adding another terminator after each commit has been
shown will end up with doubled newlines for short user
formats (like '%s'). Instead, we add the record terminator
only if it is not a newline, in which case the output will
actually contain a newline followed by the terminator.
Signed-off-by: Jeff King <redacted>
---
This one is RFC. It is missing tests, but that is because I am not
completely sure what we want the output to look like. With this change,
you still get a newline at the end of a single-line user-formatted
string, like:
$ git log -z --format:%s
three
^@two
^@one
^@
As explained above, it is not correct to simply turn that putchar('\n')
into putchar(opt->diffopt.line_termination), since it may be followed by
the diff, in which case we _want_ the newline. But maybe it makes sense
to suppress it if we have an alternate line terminator and we are not
showing the diff.
The case with a diff looks much better:
$ git log -z -p --format:%s
three
diff ...
...
^@two
diff ...
...
^@one
diff ...
...
^@
So I'm not sure if it is OK as-is, or if we should add that newline
suppression tweak. People aren't going to be looking at "-z" output as
a whole, so it is really about whether somebody saying:
git log -z --pretty=tformat:"XXX %s YYY" | perl -0ne ...
would be surprised to find a newline after "YYY" in each record.
log-tree.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
From: Jeff King <hidden> Date: 2016-06-15 22:47:00
This comment mentions the case where use_terminator is set,
but this case is not handled at all by this chunk of code.
Signed-off-by: Jeff King <redacted>
---
This comment confused me quite a bit while tracking down the issue in
2/2.
log-tree.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)