Jian
Jian

Reputation: 11060

nicely display file rename history in git log

The git command

git log --format='%H' --follow -- foo.txt

will give you the series of commits that touch foo.txt, following it across renames.

I'm wondering if there's a git log command that will also print the corresponding historical file name beside each commit.

It would be something like this, where we can interpret '%F' to be the (actually non-existent) placeholder for filename.

git log --format='%H %F' --follow -- foo.txt

I know this could be accomplished with

git log --format='%H' --follow --numstat -- foo.txt

but the output is not ideal since it requires some non-trivial parsing; each commit is strewn across multiple lines, and you'll still need to parse the file rename syntax ("bar.txt => foo.txt") to find what you're looking for.

Upvotes: 23

Views: 6416

Answers (3)

Bill Chan
Bill Chan

Reputation: 3455

This works in OSX terminal:

git log --format='%%%h' --name-only --follow -- README.md | xargs echo | perl -pe 's/\%/\n/g'

Upvotes: 0

FoolishSeth
FoolishSeth

Reputation: 4021

You can simplify it a little bit like this:

git log --format='%H' --name-only --follow -- README.md

which will give you output kind of like this

621175c4998dfda8da

README.md
d0d6ef0a3d22269b96

README.md

which should be a little easier to parse. For instance you can use a sentinel and sed out the newlines like this:

git log --format='%H%%' --name-only --follow -- README.md | sed ':a;N;$!ba;s/%\n\n/ /g'

which should give you the hash and the filename on the same line:

621175c4998dfda8da README.md
d0d6ef0a3d22269b96 README.md

For info on the sed invocation, see How can I replace a newline (\n) using sed? which has the answer I based that bit on.

Upvotes: 20

mvp
mvp

Reputation: 116177

--name-status should work for you:

git log --follow --name-status --format='%H' -- foo.txt

Result will look like this and can be easily parsed by Perl or Python:

'4da4d5e3e9c24251e14d20004a853b72bd096cce'

R100    b.txt   c.txt
'4966238c97198d096f0424a0a23ec550297d8086'

M       b.txt
'c0e41c11f0f7c5a7650cedfbad138c8941444023'

R100    a.txt   b.txt
'4b2318c0fbabd836d50cabd70bf19013d3964856'

A       a.txt

If you insist to get it in one line, this Perl one-liner does the trick (it works on Windows as is. On Linux, use single quotes or escape $ as \$):

git log --follow --name-status --format='%H' -- c.txt | perl -e "while(<>){chomp;print;<>;$_=<>;print q/ /,((split/\t/)[-1]);}"

which prints:

'4da4d5e3e9c24251e14d20004a853b72bd096cce' c.txt
'4966238c97198d096f0424a0a23ec550297d8086' b.txt
'c0e41c11f0f7c5a7650cedfbad138c8941444023' b.txt
'4b2318c0fbabd836d50cabd70bf19013d3964856' a.txt

Upvotes: 15

Related Questions