325

Say I have a file foo.js that was committed some time ago. I would like to simply find the commit where this file was first added.

After reading the answers and my own tinkering, this works for me

git log --follow --diff-filter=A --find-renames=40% -- foo.js
3
  • 1
    That's better than any of answers as it traces renamed files. Commented Jun 5, 2021 at 17:18
  • Think there are some edge cases where this can return more than one result e.g. when a file is added and then subsequently deleted and added again in another commit (i.e. not a rename). Seth Robinson's answer seems to handle those cases. Commented Aug 24, 2021 at 12:45
  • 1
    Out of interest, how did you decide upon 40% for --find-renames? Seems to work quite well for me and picked up some that --follow on its own didn't, just curious... Commented Aug 24, 2021 at 15:06

5 Answers 5

473

Here's simpler, "pure Git" way to do it, with no pipeline needed:

git log --diff-filter=A -- foo.js

Check the documentation. You can do the same thing for Deleted, Modified, etc.

https://git-scm.com/docs/git-log#Documentation/git-log.txt---diff-filterACDMRTUXB82308203

I have a handy alias for this, because I always forget it:

git config --global alias.whatadded "log --diff-filter=A"

This makes it as simple as:

git whatadded -- foo.js

The below one liner will recursively search through sub directories of the $PWD for foo.js without having to supply an absolute or relative path to the file, nor will the file need to be in the same directory as the $PWD

git log --diff-filter=A -- **foo.js
8
  • 34
    +1! However, my file was in a subfolder, so only worked after I added an asterisk in the front git log --diff-filter=A -- *subfolder/foo.js
    – Geo
    Commented Aug 16, 2013 at 17:40
  • 4
    How does this work on files that are merged from other branches, but which weren't necessarily added to the branch being merged by the user performing the merge?
    – user67416
    Commented Jan 22, 2014 at 18:47
  • 1
    Yep, they changed the anchor structure in the docs. Updated, thanks!
    – stelterd
    Commented Mar 20, 2019 at 20:55
  • 1
    @geo i think i get what you're saying but not really, but i have similar use case, where i generally stay within the project root of a git directory and issue commands from there, and using the supplied one liner git log --diff-filter=A -- foo.js did not print the commit ID / hash to STDOUT in my terminal rather i had to provide the relative path to the file from the git repo root in order to get the desired results
    – ipatch
    Commented Dec 11, 2019 at 20:08
  • 2
    Very nice, you know that you can put the -- in the alias too so you can write git whatadded foo.js? Commented Sep 22, 2021 at 8:23
29
git log --follow --find-renames=40% --oneline -- foo.js | tail -n 1
3
  • 2
    I'd be nice to have --follow. Commented Aug 19, 2012 at 17:31
  • 2
    The accepted solution did not work for me, but this did. Thanks! Commented Oct 16, 2019 at 15:55
  • I've edited the answer to include both --follow and --find-renames=40% so it follows file renames and will find the original author - hope this is OK? Commented Aug 24, 2021 at 14:14
8

The following may not be of your interest, but I think it will help you in the future and is part of the debugging ecosystem in Git:

You can use git-blame to show what revision and author last modified each line of a file, especially a file annotation. Visit https://git-scm.com/book/en/v2/Git-Tools-Debugging-with-Git

For example,

git blame -L 174,190  xx.py

The -L option is to restrict the output of the annotation to lines 174 through 190, so you will see the authors and the commit hash, etc from line 174 until 190 for the file xx.py

2
  • Could you explain please what each of the operands do? I realise you have provided a link to the relevant rtfm, but a little elucidation would make your post a one-stop shop.
    – rossmcm
    Commented Feb 6, 2017 at 22:25
  • As Pro-Git book says If you track down a bug in your code and want to know when it was introduced and why, file annotation is often your best tool. It shows you what commit was the last to modify each line of any file, so this example that I showed uses the -L option to limit the output to lines 174 through 190 and the last thing is just the target file you want to check (xx.py) in this case a python file @rossmcm
    – Reidel
    Commented Feb 23, 2017 at 16:46
3

If it's an alternative to do it non-programatically, this is very quick. Open gitk GUI.

gitk file

Then just scroll to the first commit

2
  • I think it will be scroll to the last commit. Commented Apr 8 at 12:56
  • The first commit can be the one created first. It doesn't have to be the one you see first.
    – Martin G
    Commented Apr 8 at 15:43
0

The command is:

git log --reverse --oneline -- foo.js

The topmost commit is the answer.

To be more specific:

git log --reverse --oneline -- foo.js | head -n 1

Not the answer you're looking for? Browse other questions tagged or ask your own question.