Pi Fisher
Pi Fisher

Reputation: 270

git ls-files for different branch

I want to find all markdown files in the base directory of a specified branch. git ls-files was suggested to me, but the documentation doesn't mention specifying a branch. I want to be able to do this without checking out that branch. Can this be done?

Upvotes: 4

Views: 1838

Answers (2)

torek
torek

Reputation: 487855

git ls-files examines files in the index or the work-tree (or both). Since the current index and work-tree contents generally reflect the current commit as extracted from the tip of the current branch, it won't work this way. But there is a workaround.

As VonC notes, git ls-tree examines a tree object, such as that stored in a commit. However, git ls-tree does not accept pathspec arguments such as **/*.md.

The workaround is to read the commit of interest into a temporary index. To do that cleanly, use mktemp to make a temporary file, then remove the temporary file and use git read-tree to re-create the file as valid a temporary index containing the image of the commit you wish to inspect, which you can then inspect with git ls-files. For example:

$ cd git
$ sh -c 'export GIT_INDEX_FILE=$(mktemp); rm $GIT_INDEX_FILE; git read-tree e83c5163316f89bfbde7d9ab23ca2e25604af290; git ls-files -- "*.h" "**/*.h"; rm $GIT_INDEX_FILE'
cache.h
$ sh -c 'export GIT_INDEX_FILE=$(mktemp); rm $GIT_INDEX_FILE; git read-tree origin/master; git ls-files -- "*.md"; rm $GIT_INDEX_FILE'
.github/CONTRIBUTING.md
.github/PULL_REQUEST_TEMPLATE.md
README.md
contrib/vscode/README.md

(Note: the sh -c 'export ...; cmd1; cmd2; cmd3' is all required, although if you're already using a POSIX-compatible shell you can replace sh -c with parentheses for a subshell. We need the environment variable GIT_INDEX_FILE to stay set for just those commands. If your mktemp has -u, consider using that instead of the first rm. See also How portable is mktemp(1)?)

Upvotes: 6

VonC
VonC

Reputation: 1323503

If you are using git ls-tree, you might need to filter the output yourself, to grep what you need.

As mentioned in this thread back in 2012:

There are two uses of "pattern" there, and the former is probably OK but the latter is indeed misleading.

Back when we wrote this command, there were two distinct "pathspec" families, and ls-tree belong to the one with "diff" family that did not take anything but "leading path pattern" (the other one from "ls-files" and "grep" family allowed wildcards). Giving a wildcard to the command in the "ls-tree/diff" family was never supported.

If you change ls-tree to use its paths arguments as pathspec, you will break backward compatibility.

Upvotes: 4

Related Questions