8

The solution that works for file does not work for directory. How do I know the first git commit that created a directory for the first time?

EDIT: As one of the comment points out that a directory appears in git only when a file under that directory is added to version control. In the context of this question, I don't know which file under that directory was added first.

sherlock
  • 2,397
  • 3
  • 27
  • 44
  • 3
    Correct me if I'm wrong, but I believe directories aren't logged in the same way that files are, e.g. because you need to have a file in a new directory to add it. So I would think that you would need to find out when the first file in the directory was commited. – Tucker Boniface Feb 13 '18 at 04:49
  • I clarified your doubt. – sherlock Feb 13 '18 at 05:27

4 Answers4

10

Best way I know to check a path in a lot of commits quickly is with git cat-file --batch-check. List your commits in reverse i.e. oldest first with the path you're interested in and feed that to the batch checker, it will complain if the path is missing but it does so to stdout, so you can print the first line with an absence of complaints:

git log --reverse --pretty=$'%H:path/to/folder\t%H' \
| git cat-file --batch-check='%(rest)' \
| awk 'NF==1 { print;exit; }'
jthill
  • 55,082
  • 5
  • 77
  • 137
2

One possible approach would be, for all files of a folder, to check when that file was added.

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

But simply using the log for that folder can also help:

git log -- path/to/folder
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 1
    Found this helpful, would be nice to be able to reference dir creation specifically, but good enough - bit of an edge case where someone adds just an empty foldere – Scott Anderson Jan 19 '21 at 14:37
2

You can use git bisect to find when something changed in a certain way. It operates off the assumption that the repository was right in the past, but something happened recently to make it not-right.

For this example, "good" is the directory not existing, and "bad" is the directory existing.

First you find a commit where it's "bad":

$ ls -d MyDirectory
MyDirectory/
$ git bisect start
$ git bisect bad

Then you find a commit where it's "good"

$ git checkout HEAD~1000
$ ls -d MyDirectory
ls: cannot access 'MyDirectory': No such file or directory
$ git bisect good

Then you either repeatedly do manual bisect good/bad:

$ if [ -d MyDirectory ]; then git bisect bad; else git bisect good; fi

Or you use bisect run:

$ git bisect run [ ! -d MyDirectory ]

At the end it'll tell you the first "bad" commit.

amphetamachine
  • 27,620
  • 12
  • 60
  • 72
2

Building on @VonC's answer, use --reverse with some awkward post-processing (sadly, --reverse is applied to the log after -n 1), we get:

git log -- path/to/folder | awk 'NR>1 {print last} {last=$0}; /^commit/ && ++c==2{exit}'
Cameron Stone
  • 857
  • 1
  • 8
  • 10