changed-files
Effortlessly track all changed files and directories relative to a target branch, the current branch (preceding commit or the last remote commit), multiple branches, or custom commits returning relative paths from the project root using this GitHub action.
[!NOTE]
This action solely identifies files that have changed for events such as
pull_request*
,push
,merge_group
,release
, and many more. However, it doesn't detect pending uncommitted changes created during the workflow execution.See: https://github.com/tj-actions/verify-changed-files instead.
Table of contents
- Features 🚀
- Usage 💻
- Inputs ⚙️
- Useful Acronyms 🧮
- Outputs 📤
- Versioning 🏷️
- Examples 📄
- Real-world usage 🌐
- Important Notice ⚠️
- Migration guide 🔄
- Credits 👏
- Report Bugs 🐛
- Contributors ✨
Features 🚀
- Fast execution, averaging 0-10 seconds.
- Leverages either Github's REST API or Git's native diff to determine changed files.
- Facilitates easy debugging.
- Scales to handle large/mono repositories.
- Supports Git submodules.
- Supports merge queues for pull requests.
- Generates escaped JSON output for running matrix jobs based on changed files.
- Lists changed directories.
- Limits matching changed directories to a specified maximum depth.
- Optionally excludes the current directory.
- Writes outputs to a designated
.txt
or.json
file for further processing. - Restores deleted files to their previous location or a newly specified location.
- Supports fetching a fixed number of commits which improves performance.
- Compatible with all platforms (Linux, MacOS, Windows).
- Supports GitHub-hosted runners.
- Supports GitHub Enterprise Server.
- Supports self-hosted runners.
- Lists all files and directories that have changed:
- Between the current pull request branch and the last commit on the target branch.
- Between the last commit and the current pushed change.
- Between the last remote branch commit and the current HEAD.
- Restricts change detection to a subset of files and directories:
- Provides boolean output indicating changes in specific files.
- Uses Glob pattern matching.
- Supports Globstar.
- Supports brace expansion.
- Supports negation.
- Uses YAML syntax for specifying patterns.
- Supports YAML anchors & aliases.
- Supports YAML multi-line strings.
And many more...
Usage 💻
[!IMPORTANT]
- Push Events: When configuring
actions/checkout
, make sure to setfetch-depth
to either0
or2
, depending on your use case.- Mono Repositories: To avoid pulling the entire branch history, you can utilize the default
actions/checkout
'sfetch-depth
of1
forpull_request
events.- Quoting Multiline Inputs: Avoid using single or double quotes for multiline inputs. The value is already a string separated by a newline character. Refer to the Examples section for more information.
- Credentials Persistence: If
fetch-depth
is not set to 0, make sure to setpersist-credentials
totrue
when configuringactions/checkout
.- Matching Files and Folders: To match all files and folders under a directory, this requires a globstar pattern e.g.
dir_name/**
which matches any number of subdirectories and files.
Visit the discussions for more information or create a new discussion for usage-related questions.
On pull_request
🔀
Detect changes to all files in a Pull request relative to the target branch or since the last pushed commit.
Using local .git directory 📁
name: CI
on:
pull_request:
branches:
- main
jobs:
# ------------------------------------------------------------------------------------------------------------------------------------------------
# Event `pull_request`: Compare the last commit of the main branch or last remote commit of the PR branch -> to the current commit of a PR branch.
# ------------------------------------------------------------------------------------------------------------------------------------------------
changed_files:
runs-on: ubuntu-latest # windows-latest || macos-latest
name: Test changed-files
steps:
- uses: actions/checkout@v4
# -----------------------------------------------------------------------------------------------------------
# Example 1
# -----------------------------------------------------------------------------------------------------------
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
# To compare changes between the current commit and the last pushed remote commit set `since_last_remote_commit: true`. e.g
# with:
# since_last_remote_commit: true
- name: List all changed files
env:
ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
run: |
for file in ${ALL_CHANGED_FILES}; do
echo "$file was changed"
done
# -----------------------------------------------------------------------------------------------------------
# Example 2
# -----------------------------------------------------------------------------------------------------------
- name: Get all changed markdown files
id: changed-markdown-files
uses: tj-actions/changed-files@v44
with:
# Avoid using single or double quotes for multiline patterns
files: |
**.md
- name: List all changed files markdown files
if: steps.changed-markdown-files.outputs.any_changed == 'true'
env:
ALL_CHANGED_FILES: ${{ steps.changed-markdown-files.outputs.all_changed_files }}
run: |
for file in ${ALL_CHANGED_FILES}; do
echo "$file was changed"
done
# -----------------------------------------------------------------------------------------------------------
# Example 3
# -----------------------------------------------------------------------------------------------------------
- name: Get all test, doc and src files that have changed
id: changed-files-yaml
uses: tj-actions/changed-files@v44
with:
files_yaml: |
doc:
- '**.md'
- docs/**
test:
- test/**
- '!test/**.md'
src:
- src/**
# Optionally set `files_yaml_from_source_file` to read the YAML from a file. e.g `files_yaml_from_source_file: .github/changed-files.yml`
- name: Run step if test file(s) change
# NOTE: Ensure all outputs are prefixed by the same key used above e.g. `test_(...)` | `doc_(...)` | `src_(...)` when trying to access the `any_changed` output.
if: steps.changed-files-yaml.outputs.test_any_changed == 'true'
env:
TEST_ALL_CHANGED_FILES: ${{ steps.changed-files-yaml.outputs.test_all_changed_files }}
run: |
echo "One or more test file(s) has changed."
echo "List all the files that have changed: $TEST_ALL_CHANGED_FILES"
- name: Run step if doc file(s) change
if: steps.changed-files-yaml.outputs.doc_any_changed == 'true'
env:
DOC_ALL_CHANGED_FILES: ${{ steps.changed-files-yaml.outputs.doc_all_changed_files }}
run: |
echo "One or more doc file(s) has changed."
echo "List all the files that have changed: $DOC_ALL_CHANGED_FILES"
# -----------------------------------------------------------------------------------------------------------
# Example 4
# -----------------------------------------------------------------------------------------------------------
- name: Get changed files in the docs folder
id: changed-files-specific
uses: tj-actions/changed-files@v44
with:
files: docs/*.{js,html} # Alternatively using: `docs/**`
files_ignore: docs/static.js
- name: Run step if any file(s) in the docs folder change
if: steps.changed-files-specific.outputs.any_changed == 'true'
env:
ALL_CHANGED_FILES: ${{ steps.changed-files-specific.outputs.all_changed_files }}
run: |
echo "One or more files in the docs folder has changed."
echo "List all the files that have changed: $ALL_CHANGED_FILES"
Using Github's API :octocat:
name: CI
on:
pull_request:
branches:
- main
jobs:
# -------------------------------------------------------------
# Event `pull_request`: Returns all changed pull request files.
# --------------------------------------------------------------
changed_files:
# NOTE:
# - This is limited to pull_request* events and would raise an error for other events.
# - A maximum of 3000 files can be returned.
# - For more flexibility and no limitations see "Using local .git directory" above.
runs-on: ubuntu-latest # windows-latest || macos-latest
name: Test changed-files
permissions:
pull-requests: read
steps:
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
- name: List all changed files
env:
ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
run: |
for file in ${ALL_CHANGED_FILES}; do
echo "$file was changed"
done
On push
⬆️
Detect changes to files made since the last pushed commit.
name: CI
on:
push:
branches:
- main
jobs:
# -------------------------------------------------------------
# Using GitHub's API is not supported for push events
# -------------------------------------------------------------
#
# ----------------------------------------------------------------------------------------------
# Using local .git history
# ----------------------------------------------------------------------------------------------
# Event `push`: Compare the preceding remote commit -> to the current commit of the main branch
# ----------------------------------------------------------------------------------------------
changed_files:
runs-on: ubuntu-latest # windows-latest || macos-latest
name: Test changed-files
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # OR "2" -> To retrieve the preceding commit.
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
# NOTE: `since_last_remote_commit: true` is implied by default and falls back to the previous local commit.
- name: List all changed files
env:
ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
run: |
for file in ${ALL_CHANGED_FILES}; do
echo "$file was changed"
done
...
Other supported events :electron:
- schedule
- release
- workflow_dispatch
- workflow_run
- merge_group
- issue_comment
- ...and many more
To access more examples, navigate to the Examples section.
If you feel generous and want to show some extra appreciation:
Support this project with a :star:
[!IMPORTANT]
- When using
files_yaml*
inputs:
All keys must start with a letter or
_
and contain only alphanumeric characters,-
, or_
.For example,
test
ortest_key
ortest-key
or_test_key
are all valid choices.
Inputs ⚙️
- uses: tj-actions/changed-files@v44
id: changed-files
with:
# Github API URL.
# Type: string
# Default: "${{ github.api_url }}"
api_url: ''
# Specify a different base commit
# SHA or branch used for
# comparing changes
# Type: string
base_sha: ''
# Exclude changes outside the current
# directory and show path names
# relative to it. NOTE: This
# requires you to specify the
# top-level directory via the `path`
# input.
# Type: boolean
# Default: "true"
diff_relative: ''