0

To list all the files in a commit, I can use:

git show --pretty="" --name-only bd61ad98    

However if I want to further narrow down the list to only files in a folder, what should I do? How about files not just in one folder but:

  • in several folder?
  • not in a folder?
  • not in several folders?
Ooker
  • 1,969
  • 4
  • 28
  • 58
  • You can't do this with `git show`. Either check out the commit and use `git ls-files`, or use `grep` to filter the output of `git show`. – user229044 Sep 01 '23 at 18:13
  • Files are not "stored" in commits. If you want to see changes between commits, you can always use `git diff`. – Caleb Sep 01 '23 at 19:02
  • 2
    `git show --name-only` doesn't list **all** files in the commit, it only list files changed from the previous commit. Do you want to list **all** files or modified files? – phd Sep 01 '23 at 19:31
  • @phd I see. I want to list all files – Ooker Sep 02 '23 at 05:31
  • `git ls-tree --name-only -r bd61ad98 subdir1 subdi2` – phd Sep 02 '23 at 08:40

2 Answers2

2

git ls-tree $commit:$path answers your question as asked, but I think you're after all the files that changed in that folder.

git diff-tree -m $commit{~,}:$path, with --name-status or --name-only if you want, or if you want the full path listed and not the that-path-relative names, git diff-tree -m -r $commit{~,} -- $path.

For multiple paths, either run multiple commands or use the separated form, $commit{~,} -- $path and give multiple paths; to take all paths except some see the pathspec docs, you can use ":!$path"

jthill
  • 55,082
  • 5
  • 77
  • 137
  • How can this be used to exclude multiple folders at the same time? – Paolo Sep 01 '23 at 20:53
  • Multiple folders, just list them all. Exclusion, see the pathspec docs in `git help glossary`, `':!path'` – jthill Sep 01 '23 at 21:26
  • So something like `git diff-tree -m -r bd61ad98{~,} ':!foo' ':!bar'` ? that seems to throw ugly errors if any of the folders do not exist – Paolo Sep 02 '23 at 08:33
  • I added a `--` separator to disambiguate the args, that made that little wart go away. It was (wrongly imo) trying to interpret them as revisions first and getting confused. – jthill Sep 02 '23 at 16:04
0

Here's a solution using awk.


In folder foo:

$ folder="foo"
$ git show --pretty="" --name-only bd61ad98 | awk -F'/' -v folder="$folder" '$1 ~ folder'

Not in folder foo:

$ folder="foo"
$ git show --pretty="" --name-only bd61ad98 | awk -F'/' -v folder="$folder" '$1 !~ folder'

Not in folder foo nor bar:

$ first_folder="foo"
$ second_folder="bar"
$ git show --pretty="" --name-only bd61ad98 | awk -F'/' -v first_folder="$first_folder" -v second_folder="$second_folder" '$1 !~ first_folder && $1 !~ second_folder'
Paolo
  • 21,270
  • 6
  • 38
  • 69
  • Thank you for your feedback, anonymous downvoter – Paolo Sep 01 '23 at 19:04
  • Yeah, I agree that a comment from the downvoter would have been more constructive indeed. Meh. My first guess would be that it's for the use of an external tool (`awk`) not available in all terminals, when a pure git solution exists? Then again, I don't know, and I found your answer useful. I upvoted both answers. – Romain Valeri Sep 01 '23 at 20:40
  • I'm not the downvoter but this will not work for interior folders like `foo/bar`, and the extension to nested folders is not going to be easy to find for anyone who'd need to ask this question. – jthill Sep 01 '23 at 22:29
  • @jthill it can easily be adapted for internal folders, but OP didn't specify that requirement – Paolo Sep 02 '23 at 08:34