4

I'm trying to figure out at which point a line in a file was introduced and in which commits it was changed.

I can view the history of those lines (line 10 in the file example.txt):

git log -L 10,11:example.txt

However, for each log entry it includes a 'diff' or a 'patch' (I'm not really sure of the difference yet) as if I'd run:

git log -p

This makes the output more difficult to read - I just want to view a list of commit messages and their ids for commits that changed the line(s) I'm interested in.

For example, ordinarily git logs can be simplified by using the --pretty formats, enabling us to read through a clean list of commit messages to find the info we're interested in. For example, I use the --oneline option frequently:

git log --oneline

That however shows the full log - we want to filter this to only show commits that changed lines of interest. Something like the following would be great but the pretty oneline format doesn't seem to work in combination with the -L flag:

git log --oneline -L 10,11:example.txt

I've tried various combinations of options and arguments from the git log documentation but haven't found anything that works.

Does anyone else face this issue or have any ideas of what could work?

Thanks for reading this far

stu0292
  • 471
  • 4
  • 7
  • Giving a command line based answer is way beyond my pay grade, but I can tell you that most IDEs which have Git integration (e.g. IntelliJ, Eclipse), can annotate each line in a source file with information about who last touched a given line. Actually, I'd rather get this information in a graphic way rather than from the command line. – Tim Biegeleisen Aug 09 '17 at 09:48
  • Have since found [this post](https://stackoverflow.com/questions/41427590/git-log-l-without-diff) an answer to which suggests using the git log -L command as normal and extracting the commits with egrep. Not sure how yet... – stu0292 Aug 09 '17 at 09:52

2 Answers2

3

As mentioned by VonC here,

git log -s -L <start>,<end>:file
# and 
git log -s -L :<funcname>:file

should both work to suppress the patch output with Git >= 2.22.0. This was added in commit 9f607cd09c (line-log: suppress diff output with "-s", 2019-03-07).

Also, you mention that

git log --oneline -L 10,11:example.txt

does not work. --oneline should only apply to the commit header, and not the diff output ( --oneline -p would show the commit information on one line and then the diff ouptut).

I checked with Git 2.13.3 (released July 12 2017, so around the time you posted your question) and git log --oneline -L 10,11:example.txt does work (it does however output the full patch).

philb
  • 2,031
  • 15
  • 20
0

a couple of verbose solutions are to use the normal git log -L command to output the log for the lines of interest then pipe the output to grep or sed to print only the parts of the commit message you're interested in. Try which ever version you prefer. Would love to hear if anyone has a less verbose solution!

grep:

git log -L 10,11:example.txt | grep 'commit \w' -A 4

The grep command matches the first line of each log entry and the prints the next 4 lines with the -A flag

sed:

git log -L 10,11:example.txt | sed -n '/commit/{p;n;n;n;n;p}' 

when it finds a match, prints the line via the p command, skips the next lines via the n command then prints the next line using p. The leading -n option prevents all other printing. found thanks to this answer

stu0292
  • 471
  • 4
  • 7
  • This is astonishing that using the `--format` option to `git log` still emits the diff and there is no option that I can see to turn off the diff output, so as to get the exact output that is desired. This is not 100% reliable to grep through the output without some amazing trickery: What if the diff output itself contains something that you are trying to match in the piped-to egrep? Amazing trickery example: `uuid=$(uuidgen); git log -2 --pretty=tformat:"$uuid %h" -L 16,16:some_file.org | sed -n "s%^$uuid %%gp"` – bgoodr Aug 10 '19 at 16:11