How to find the commit in which a given file was added?
Asked Answered
H

4

320

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
Hollis answered 18/7, 2012 at 1:44 Comment(3)
That's better than any of answers as it traces renamed files.Courtund
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.Ailssa
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...Ailssa
C
467

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
Chantey answered 28/11, 2012 at 4:52 Comment(8)
+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.jsNonprofit
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?Junta
The doc link above doesn't jump to the flag info. Maybe it changed since posted. git-scm.com/docs/git-log#Documentation/…Chalybeate
Yep, they changed the anchor structure in the docs. Updated, thanks!Chantey
@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 resultsBobsleigh
I would add --oneline to this, for a more condensed list of commits.Finned
Very nice, you know that you can put the -- in the alias too so you can write git whatadded foo.js?Chesterfield
@AndreasMagnusson yes! leaving the -- out though makes the alias more usable for me as you can still add other flags if you omit the -- part as all following arguments are interpreted as file/glob expressions. Also the -- is such muscle memory before file/glob args I'd wind up typing it anyway :)Chantey
D
28
git log --follow --find-renames=40% --oneline -- foo.js | tail -n 1
Disparage answered 18/7, 2012 at 1:46 Comment(3)
I'd be nice to have --follow.Pomeroy
The accepted solution did not work for me, but this did. Thanks!Latinism
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?Ailssa
W
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

Witness answered 24/1, 2017 at 18:49 Comment(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.Quasar
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 @QuasarWitness
H
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

Hagiographer answered 24/8, 2021 at 14:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.