49

Is there a way (from the command line) to list the names of all files changed in a PR in Git/GitHub? This would be used to find what tests need to be run in a Travis CI build for that PR.

The CI build runs these commands before it calls our script:

git clone --depth=50 git://github.com/jekyll/jekyll.git jekyll/jekyll
cd jekyll/jekyll
git fetch origin +refs/pull/2615/merge
git checkout -qf FETCH_HEAD
Alfred Xing
  • 4,406
  • 2
  • 23
  • 34

12 Answers12

54

In general, you can list the files changed between any two commits with git diff --name-only :

How to list only the file names that changed between two commits?

The problem here seems to be determining the 'merge base'. If all branches originate with master, then you could do:

git --no-pager diff --name-only FETCH_HEAD $(git merge-base FETCH_HEAD master)

This will show you the changes between the point at which the FETCH_HEAD was branched from master to the current FETCH_HEAD. I tested this locally, and the PR branches are cut from master I believe it should work.

Noam Hacker
  • 4,671
  • 7
  • 34
  • 55
zanerock
  • 3,042
  • 3
  • 26
  • 35
  • 1
    I'm a bit confused about `git diff`... If changes to `master` were made after the PR was submitted, will this command include those changes? (I don't want them to be included) – Alfred Xing Aug 01 '14 at 15:56
  • 2
    True, but wouldn't you want to test those changes as well? If A were changed in the PR and B changed on master since the PR, there may be an interaction between B and A such that tests for A would pass but tests on B fail. – zanerock Aug 01 '14 at 22:42
  • 1
    Valid point. But specifically, this would not be the case here since the two parts don't interact at all. I'm trying to see if a PR has or has not modified the `site` directory in the repo, and if it has, run [HTML::Proofer](https://github.com/gjtorikian/html-proofer) on it. – Alfred Xing Aug 02 '14 at 05:49
  • 1
    You can actually write this much simpler: `git --no-pager diff --name-only FETCH_HEAD...master` (note the three dots). For more info, see [here](http://stackoverflow.com/a/7256391/2063031). – ostrokach Dec 26 '16 at 07:49
  • 2
    ostrokach: are you saying that `git --no-pager diff --name-only FETCH_HEAD...master` is equivalent to `git --no-pager diff --name-only FETCH_HEAD $(git merge-base FETCH_HEAD master)`? I tried this locally and did not get the same results. – zanerock Feb 23 '17 at 17:42
  • 1
    Using `FETCH_HEAD` is problematic in general, because it can point to multiple branches, so you may see diffs between this PR and other branches, not just `master`. It works in the OP's case because they start with a clean `git clone`, but in general and in the OP's case (because of the `git checkout`) `git --no-pager diff --name-only master...HEAD` works and is safer, in that it will only compare against the master branch. – Old Pro Feb 13 '20 at 19:52
  • I was just using `git diff --name-only master...` with the three dots and it worked for a long time now on a particular branch it doesn't. Thie above answer isnt working either. Both show 76 files changes when only 8 files changed in the PR.. Does anyone know what logic GitHub uses to figure this out? – Brad Mar 10 '20 at 21:45
  • PS others might find this useful https://developer.github.com/v3/pulls/#list-pull-requests-files if I end up trying it and it works I'll come back and post an answer. – Brad Mar 10 '20 at 21:50
32

Using GitHub cli (gh) you can run:

gh pr view 2615 --json files --jq '.files.[].path'

I have made a gh alias because I use it regularly:

gh alias set pr_files "pr view $1 --json files --jq '.files.[].path'"

and then I call it with gh pr_files 2615 or gh pr_files 2615 | cat

gh pr_files 2615 | cat
zoispag
  • 371
  • 1
  • 4
  • 8
  • 1
    You are amazing @zoispag I'm using this in a script to create a manifest for a PR. Thank you – MayTheSForceBeWithYou Feb 08 '22 at 18:17
  • unfortunately limited to 100 files. There is a current open issues about this https://github.com/cli/cli/issues/5415 – Christophe Vidal May 03 '22 at 19:25
  • @ChristopheVidal thanks for sharing! Are you sure it’s about files? From the issue, it looks like it’s 100 commits. Unless the “100” restrictions applies to any resource requested as json. – zoispag May 04 '22 at 20:11
  • fair enough, actually this is here https://github.com/cli/cli/issues/5368. I suppose that there is a limit of 100 for everything. – Christophe Vidal May 04 '22 at 21:28
  • 1
    This is cool, thanks. What about an answer to this one? https://superuser.com/questions/1735568/how-to-search-pull-requests-on-github-targeting-specific-file . Basically it's the reverse question, which PRs touch the file, instead of which files are in the PR. I suppose one could loop around thousands of PRs and filter, but I doubt the API would allow all that? Anyone got a solution? – pgr Nov 19 '22 at 12:43
9

For GitHub specifically, this can be accomplished using the REST API:

GET /repos/:owner/:repo/pulls/:pull_number/files

You can use one of the GitHub libraries for this purpose.

ajaykarpur
  • 178
  • 1
  • 6
  • Important to note, this will return an object for every commit in the pull, and you'll have to iterate over each of them. – Kraken Jul 11 '23 at 14:30
5

Chrome console...

Note: This will break if Github changes the tags/classes/IDs in the page.

const fileElems = document.querySelectorAll('#files div.js-diff-progressive-container div.file div.file-header div.file-info a.Link--primary');
const filePaths = [];
        
for (let a of fileElems) {
    filePaths.push(a.title);
}
    
const filePathsStr = filePaths.join('\n');
console.log(filePathsStr);
copy(filePathsStr);
console.log('Copied to the clipboard as well ');
matt
  • 333
  • 2
  • 10
  • 23
AdamHickey
  • 59
  • 1
  • 3
1

Google search sent me here though it is slightly different question.

This question [details] has command-line. However, I needed the list of files, its ok if I can see in GUI

Here a way to see list of files in GUI:

  1. open the pull request

  2. click on the [Files changed] tab

    Conversation 0 Commits 3 [Files changed] 8

  3. click on drop down after 'n files' in the below line of [Files changed]

    Changes from all commits v ... [8 files v] ... +638 −266

(click on the v, drop down, after files in the above line)

Manohar Reddy Poreddy
  • 25,399
  • 9
  • 157
  • 140
1

I couldn't find a way to see just the list of changed files in GitHub (i.e. without the diff and comments), but it can be done with this one-liner in the browser console:

Array.from(document.getElementsByClassName('js-details-target')).forEach((e) => {e.click();})

This will collapse all the diff blocks leaving only the filenames.

laurent
  • 88,262
  • 77
  • 290
  • 428
  • 9
    This can also be done by pressing the "alt" key (or "option" on Mac) and clicking on the inverted caret icon next to any file, it will collapse all of them: https://github.blog/changelog/2018-08-17-collapse-all-diffs-in-a-pull-request-at-once/ – Nagev Jun 26 '19 at 13:46
1

Here is the simple method:

  1. Generate below url for POST request https://dev.azure.com/**{OranizationName}**/_apis/Contribution/HierarchyQuery/project/**{ProjectID}**?api-version=5.0-preview.1
  2. Refer this link for any value you need https://learn.microsoft.com/en-us/rest/api/azure/devops/?view=azure-devops-rest-5.1
  3. Use below Json as a request param {"contributionIds":["ms.vss-code-web.pr-detail-data-provider"],"dataProviderContext":{"properties":{"pullRequestId":{PullRequestID},"repositoryId":"{repositoryId}","sourcePage":{"url":"https://dev.azure.com/{OrganizationName}/{ProjectName}/_git/{RepositoryName}/pullrequest/{PullRequestID}?_a=files"}}}}
  4. Send POST request
  5. Get Count from highlighted property to get the file count for each PR enter image description here

6. Create access token in Azure DevOps and use it for authentication 7. Provide Code and Token Administration access to token

Ramanujam Allam
  • 1,300
  • 12
  • 11
1

According to @AdamHickey's 2019 answer, update the tag's class to 'Link--primary' as below

// the changes were only done on the **line** below
const fileElems = document.querySelectorAll('#files div.file-info a.Link--primary');
const filePaths = [];

for (let a of fileElems) {
    filePaths.push(a.title);
}

const filePathsStr = filePaths.join('\n');
console.log(filePathsStr);
copy(filePathsStr);
console.log('Copied to the clipboard as well ');
Mureinik
  • 297,002
  • 52
  • 306
  • 350
1

The alternative to zoispag's answer (using the new GitHub CLI 2.14.5) and gh pr diff:

gh pr diff --name-only

From PR 6074 and issue 6060.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
0

Inspired by @AdamHickey, that answer was not working anymore. So, I created a working script.

let changes = document.getElementsByClassName("file-info");
let files = []
for(let i =0;i<changes.length;i++)
{
    files.push(changes[i].getElementsByClassName("link-gray-dark")[0].title);
    

}
navigator.clipboard.writeText(JSON.stringify(files));

Disclaimer: This may stop working if someday the structure of html change.

Aman Jain
  • 655
  • 5
  • 17
0

There are some ways to find changed files but you have to experiment on what you compare. Two examples that I mainly use in GitHub Actions are:

git --no-pager diff --name-only --diff-filter=ACMRT ${{github.event.pull_request.base.sha}} ${{ github.event.pull_request.head.sha }}

and:

git --no-pager diff --name-only --diff-filter=ACMRT ${{github.event.pull_request.base.sha}} ${{github.sha}}

This results in a list such as:

.github/workflows/potato.yml
.tomato.yml
app/assets/javascripts/cucumber.js

Experiment with the SHA signatures according to your needs.

George Ts.
  • 91
  • 1
  • 4
0

A total hacky, not 100% fool proof, but easy way to get this, for all files touched in a PR is to:

  • Select all the text in the page of the PR and then copy it to the clipboard (so basically CMD+A, CMD+C on a mac)
  • run pbpaste | grep 'src/', for example, if you have a java project. This sends the text that's on the clipboard to grep.
  • Maybe you get lucky and this works for you (probably will if you have a java project)
  • if not, change the grep part to something that hopefully targets files in your project
Brad Parks
  • 66,836
  • 64
  • 257
  • 336