diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index c28e771..8d5fffd 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -72,6 +72,19 @@ jobs:
         shell: bash
         run: __test__/verify-side-by-side.sh
 
+      # Sparse checkout
+      - name: Sparse checkout
+        uses: ./
+        with:
+          sparse-checkout: |
+            __test__
+            .github
+            dist
+          path: sparse-checkout
+
+      - name: Verify sparse checkout
+        run: __test__/verify-sparse-checkout.sh
+
       # LFS
       - name: Checkout LFS
         uses: ./
diff --git a/README.md b/README.md
index 8fe140f..14b4366 100644
--- a/README.md
+++ b/README.md
@@ -74,6 +74,11 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
     # Default: true
     clean: ''
 
+    # Do a sparse checkout on given patterns. Each pattern should be separated with
+    # new lines
+    # Default: null
+    sparse-checkout: ''
+
     # Number of commits to fetch. 0 indicates all history for all branches and tags.
     # Default: 1
     fetch-depth: ''
@@ -106,6 +111,8 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
 
 # Scenarios
 
+- [Fetch only the root files](#Fetch-only-the-root-files)
+- [Fetch only the root files and `.github` and `src` folder](#Fetch-only-the-root-files-and-github-and-src-folder)
 - [Fetch all history for all tags and branches](#Fetch-all-history-for-all-tags-and-branches)
 - [Checkout a different branch](#Checkout-a-different-branch)
 - [Checkout HEAD^](#Checkout-HEAD)
@@ -116,6 +123,24 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
 - [Checkout pull request on closed event](#Checkout-pull-request-on-closed-event)
 - [Push a commit using the built-in token](#Push-a-commit-using-the-built-in-token)
 
+## Fetch only the root files
+
+```yaml
+- uses: actions/checkout@v3
+  with:
+    sparse-checkout: .
+```
+
+## Fetch only the root files and `.github` and `src` folder
+
+```yaml
+- uses: actions/checkout@v3
+  with:
+    sparse-checkout: |
+      .github
+      src
+```
+
 ## Fetch all history for all tags and branches
 
 ```yaml
diff --git a/__test__/git-auth-helper.test.ts b/__test__/git-auth-helper.test.ts
index b58010b..f2cbfa5 100644
--- a/__test__/git-auth-helper.test.ts
+++ b/__test__/git-auth-helper.test.ts
@@ -727,6 +727,7 @@ async function setup(testName: string): Promise<void> {
     branchDelete: jest.fn(),
     branchExists: jest.fn(),
     branchList: jest.fn(),
+    sparseCheckout: jest.fn(),
     checkout: jest.fn(),
     checkoutDetach: jest.fn(),
     config: jest.fn(
@@ -800,6 +801,7 @@ async function setup(testName: string): Promise<void> {
     authToken: 'some auth token',
     clean: true,
     commit: '',
+    sparseCheckout: [],
     fetchDepth: 1,
     lfs: false,
     submodules: false,
diff --git a/__test__/git-directory-helper.test.ts b/__test__/git-directory-helper.test.ts
index 02118ae..8b05606 100644
--- a/__test__/git-directory-helper.test.ts
+++ b/__test__/git-directory-helper.test.ts
@@ -462,6 +462,7 @@ async function setup(testName: string): Promise<void> {
     branchList: jest.fn(async () => {
       return []
     }),
+    sparseCheckout: jest.fn(),
     checkout: jest.fn(),
     checkoutDetach: jest.fn(),
     config: jest.fn(),
diff --git a/__test__/input-helper.test.ts b/__test__/input-helper.test.ts
index 1a8e5c9..6d7421b 100644
--- a/__test__/input-helper.test.ts
+++ b/__test__/input-helper.test.ts
@@ -79,6 +79,7 @@ describe('input-helper tests', () => {
     expect(settings.clean).toBe(true)
     expect(settings.commit).toBeTruthy()
     expect(settings.commit).toBe('1234567890123456789012345678901234567890')
+    expect(settings.sparseCheckout).toBe(undefined)
     expect(settings.fetchDepth).toBe(1)
     expect(settings.lfs).toBe(false)
     expect(settings.ref).toBe('refs/heads/some-ref')
diff --git a/__test__/verify-sparse-checkout.sh b/__test__/verify-sparse-checkout.sh
new file mode 100755
index 0000000..f668430
--- /dev/null
+++ b/__test__/verify-sparse-checkout.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+# Verify .git folder
+if [ ! -d "./sparse-checkout/.git" ]; then
+  echo "Expected ./sparse-checkout/.git folder to exist"
+  exit 1
+fi
+
+# Verify sparse-checkout
+cd sparse-checkout
+
+SPARSE=$(git sparse-checkout list)
+
+if [ "$?" != "0" ]; then
+    echo "Failed to validate sparse-checkout"
+    exit 1
+fi
+
+# Check that sparse-checkout list is not empty
+if [ -z "$SPARSE" ]; then
+  echo "Expected sparse-checkout list to not be empty"
+  exit 1
+fi
+
+# Check that all folders of the sparse checkout exist
+for pattern in $SPARSE
+do
+  if [ ! -d "$pattern" ]; then
+    echo "Expected directory '$pattern' to exist"
+    exit 1
+  fi
+done
+
+checkSparse () {
+  if [ ! -d "./$1" ]; then
+    echo "Expected directory '$1' to exist"
+    exit 1
+  fi
+
+  for file in $(git ls-tree -r --name-only HEAD $1)
+  do
+    if [ ! -f "$file" ]; then
+      echo "Expected file '$file' to exist"
+      exit 1
+    fi
+  done
+}
+
+# Check that all folders and their children have been checked out
+checkSparse __test__
+checkSparse .github
+checkSparse dist
+
+# Check that only sparse-checkout folders have been checked out
+for pattern in $(git ls-tree --name-only HEAD)
+do
+  if [ -d "$pattern" ]; then
+    if [[ "$pattern" != "__test__" && "$pattern" != ".github" && "$pattern" != "dist" ]]; then
+      echo "Expected directory '$pattern' to not exist"
+      exit 1
+    fi
+  fi
+done
\ No newline at end of file
diff --git a/action.yml b/action.yml
index cab09eb..d0c96b1 100644
--- a/action.yml
+++ b/action.yml
@@ -53,6 +53,11 @@ inputs:
   clean:
     description: 'Whether to execute `git clean -ffdx && git reset --hard HEAD` before fetching'
     default: true
+  sparse-checkout:
+    description: >
+      Do a sparse checkout on given patterns.
+      Each pattern should be separated with new lines
+    default: null
   fetch-depth:
     description: 'Number of commits to fetch. 0 indicates all history for all branches and tags.'
     default: 1
diff --git a/dist/index.js b/dist/index.js
index e6f5df8..b48bffb 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -574,6 +574,11 @@ class GitCommandManager {
             return result;
         });
     }
+    sparseCheckout(sparseCheckout) {
+        return __awaiter(this, void 0, void 0, function* () {
+            yield this.execGit(['sparse-checkout', 'set', ...sparseCheckout]);
+        });
+    }
     checkout(ref, startPoint) {
         return __awaiter(this, void 0, void 0, function* () {
             const args = ['checkout', '--progress', '--force'];
@@ -615,15 +620,18 @@ class GitCommandManager {
             return output.exitCode === 0;
         });
     }
-    fetch(refSpec, fetchDepth) {
+    fetch(refSpec, options) {
         return __awaiter(this, void 0, void 0, function* () {
             const args = ['-c', 'protocol.version=2', 'fetch'];
             if (!refSpec.some(x => x === refHelper.tagsRefSpec)) {
                 args.push('--no-tags');
             }
             args.push('--prune', '--progress', '--no-recurse-submodules');
-            if (fetchDepth && fetchDepth > 0) {
-                args.push(`--depth=${fetchDepth}`);
+            if (options.filter) {
+                args.push(`--filter=${options.filter}`);
+            }
+            if (options.fetchDepth && options.fetchDepth > 0) {
+                args.push(`--depth=${options.fetchDepth}`);
             }
             else if (fshelper.fileExistsSync(path.join(this.workingDirectory, '.git', 'shallow'))) {
                 args.push('--unshallow');
@@ -1210,20 +1218,24 @@ function getSource(settings) {
             }
             // Fetch
             core.startGroup('Fetching the repository');
+            const fetchOptions = {};
+            if (settings.sparseCheckout)
+                fetchOptions.filter = 'blob:none';
             if (settings.fetchDepth <= 0) {
                 // Fetch all branches and tags
                 let refSpec = refHelper.getRefSpecForAllHistory(settings.ref, settings.commit);
-                yield git.fetch(refSpec);
+                yield git.fetch(refSpec, fetchOptions);
                 // When all history is fetched, the ref we're interested in may have moved to a different
                 // commit (push or force push). If so, fetch again with a targeted refspec.
                 if (!(yield refHelper.testRef(git, settings.ref, settings.commit))) {
                     refSpec = refHelper.getRefSpec(settings.ref, settings.commit);
-                    yield git.fetch(refSpec);
+                    yield git.fetch(refSpec, fetchOptions);
                 }
             }
             else {
+                fetchOptions.fetchDepth = settings.fetchDepth;
                 const refSpec = refHelper.getRefSpec(settings.ref, settings.commit);
-                yield git.fetch(refSpec, settings.fetchDepth);
+                yield git.fetch(refSpec, fetchOptions);
             }
             core.endGroup();
             // Checkout info
@@ -1238,6 +1250,12 @@ function getSource(settings) {
                 yield git.lfsFetch(checkoutInfo.startPoint || checkoutInfo.ref);
                 core.endGroup();
             }
+            // Sparse checkout
+            if (settings.sparseCheckout) {
+                core.startGroup('Setting up sparse checkout');
+                yield git.sparseCheckout(settings.sparseCheckout);
+                core.endGroup();
+            }
             // Checkout
             core.startGroup('Checking out the ref');
             yield git.checkout(checkoutInfo.ref, checkoutInfo.startPoint);
@@ -1673,6 +1691,12 @@ function getInputs() {
         // Clean
         result.clean = (core.getInput('clean') || 'true').toUpperCase() === 'TRUE';
         core.debug(`clean = ${result.clean}`);
+        // Sparse checkout
+        const sparseCheckout = core.getMultilineInput('sparse-checkout');
+        if (sparseCheckout.length) {
+            result.sparseCheckout = sparseCheckout;
+            core.debug(`sparse checkout = ${result.sparseCheckout}`);
+        }
         // Fetch depth
         result.fetchDepth = Math.floor(Number(core.getInput('fetch-depth') || '1'));
         if (isNaN(result.fetchDepth) || result.fetchDepth < 0) {
diff --git a/src/git-command-manager.ts b/src/git-command-manager.ts
index ab07524..3a0ec58 100644
--- a/src/git-command-manager.ts
+++ b/src/git-command-manager.ts
@@ -16,6 +16,7 @@ export interface IGitCommandManager {
   branchDelete(remote: boolean, branch: string): Promise<void>
   branchExists(remote: boolean, pattern: string): Promise<boolean>
   branchList(remote: boolean): Promise<string[]>
+  sparseCheckout(sparseCheckout: string[]): Promise<void>
   checkout(ref: string, startPoint: string): Promise<void>
   checkoutDetach(): Promise<void>
   config(
@@ -25,7 +26,13 @@ export interface IGitCommandManager {
     add?: boolean
   ): Promise<void>
   configExists(configKey: string, globalConfig?: boolean): Promise<boolean>
-  fetch(refSpec: string[], fetchDepth?: number): Promise<void>
+  fetch(
+    refSpec: string[],
+    options: {
+      filter?: string
+      fetchDepth?: number
+    }
+  ): Promise<void>
   getDefaultBranch(repositoryUrl: string): Promise<string>
   getWorkingDirectory(): string
   init(): Promise<void>
@@ -154,6 +161,10 @@ class GitCommandManager {
     return result
   }
 
+  async sparseCheckout(sparseCheckout: string[]): Promise<void> {
+    await this.execGit(['sparse-checkout', 'set', ...sparseCheckout])
+  }
+
   async checkout(ref: string, startPoint: string): Promise<void> {
     const args = ['checkout', '--progress', '--force']
     if (startPoint) {
@@ -202,15 +213,23 @@ class GitCommandManager {
     return output.exitCode === 0
   }
 
-  async fetch(refSpec: string[], fetchDepth?: number): Promise<void> {
+  async fetch(
+    refSpec: string[],
+    options: {filter?: string; fetchDepth?: number}
+  ): Promise<void> {
     const args = ['-c', 'protocol.version=2', 'fetch']
     if (!refSpec.some(x => x === refHelper.tagsRefSpec)) {
       args.push('--no-tags')
     }
 
     args.push('--prune', '--progress', '--no-recurse-submodules')
-    if (fetchDepth && fetchDepth > 0) {
-      args.push(`--depth=${fetchDepth}`)
+
+    if (options.filter) {
+      args.push(`--filter=${options.filter}`)
+    }
+
+    if (options.fetchDepth && options.fetchDepth > 0) {
+      args.push(`--depth=${options.fetchDepth}`)
     } else if (
       fshelper.fileExistsSync(
         path.join(this.workingDirectory, '.git', 'shallow')
diff --git a/src/git-source-provider.ts b/src/git-source-provider.ts
index 48f20da..92e9d00 100644
--- a/src/git-source-provider.ts
+++ b/src/git-source-provider.ts
@@ -153,23 +153,26 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
 
     // Fetch
     core.startGroup('Fetching the repository')
+    const fetchOptions: {filter?: string; fetchDepth?: number} = {}
+    if (settings.sparseCheckout) fetchOptions.filter = 'blob:none'
     if (settings.fetchDepth <= 0) {
       // Fetch all branches and tags
       let refSpec = refHelper.getRefSpecForAllHistory(
         settings.ref,
         settings.commit
       )
-      await git.fetch(refSpec)
+      await git.fetch(refSpec, fetchOptions)
 
       // When all history is fetched, the ref we're interested in may have moved to a different
       // commit (push or force push). If so, fetch again with a targeted refspec.
       if (!(await refHelper.testRef(git, settings.ref, settings.commit))) {
         refSpec = refHelper.getRefSpec(settings.ref, settings.commit)
-        await git.fetch(refSpec)
+        await git.fetch(refSpec, fetchOptions)
       }
     } else {
+      fetchOptions.fetchDepth = settings.fetchDepth
       const refSpec = refHelper.getRefSpec(settings.ref, settings.commit)
-      await git.fetch(refSpec, settings.fetchDepth)
+      await git.fetch(refSpec, fetchOptions)
     }
     core.endGroup()
 
@@ -191,6 +194,13 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
       core.endGroup()
     }
 
+    // Sparse checkout
+    if (settings.sparseCheckout) {
+      core.startGroup('Setting up sparse checkout')
+      await git.sparseCheckout(settings.sparseCheckout)
+      core.endGroup()
+    }
+
     // Checkout
     core.startGroup('Checking out the ref')
     await git.checkout(checkoutInfo.ref, checkoutInfo.startPoint)
diff --git a/src/git-source-settings.ts b/src/git-source-settings.ts
index 2da5622..182c453 100644
--- a/src/git-source-settings.ts
+++ b/src/git-source-settings.ts
@@ -29,6 +29,11 @@ export interface IGitSourceSettings {
    */
   clean: boolean
 
+  /**
+   * The array of folders to make the sparse checkout
+   */
+  sparseCheckout: string[]
+
   /**
    * The depth when fetching
    */
diff --git a/src/input-helper.ts b/src/input-helper.ts
index 237b06a..e9a2d73 100644
--- a/src/input-helper.ts
+++ b/src/input-helper.ts
@@ -82,6 +82,13 @@ export async function getInputs(): Promise<IGitSourceSettings> {
   result.clean = (core.getInput('clean') || 'true').toUpperCase() === 'TRUE'
   core.debug(`clean = ${result.clean}`)
 
+  // Sparse checkout
+  const sparseCheckout = core.getMultilineInput('sparse-checkout')
+  if (sparseCheckout.length) {
+    result.sparseCheckout = sparseCheckout
+    core.debug(`sparse checkout = ${result.sparseCheckout}`)
+  }
+
   // Fetch depth
   result.fetchDepth = Math.floor(Number(core.getInput('fetch-depth') || '1'))
   if (isNaN(result.fetchDepth) || result.fetchDepth < 0) {