diff --git a/app/Commands/DefaultCommand.php b/app/Commands/DefaultCommand.php
index 4d487f12..e4736001 100644
--- a/app/Commands/DefaultCommand.php
+++ b/app/Commands/DefaultCommand.php
@@ -41,6 +41,7 @@ protected function configure()
                     new InputOption('test', '', InputOption::VALUE_NONE, 'Test for code style errors without fixing them'),
                     new InputOption('bail', '', InputOption::VALUE_NONE, 'Test for code style errors without fixing them and stop on first error'),
                     new InputOption('repair', '', InputOption::VALUE_NONE, 'Fix code style errors but exit with status 1 if there were any changes made'),
+                    new InputOption('diff', '', InputOption::VALUE_REQUIRED, 'Only fix files that have changed since branching off from the given branch', null, ['main', 'master', 'origin/main', 'origin/master']),
                     new InputOption('dirty', '', InputOption::VALUE_NONE, 'Only fix files that have uncommitted changes'),
                     new InputOption('format', '', InputOption::VALUE_REQUIRED, 'The output format that should be used'),
                     new InputOption('cache-file', '', InputArgument::OPTIONAL, 'The path to the cache file'),
diff --git a/app/Contracts/PathsRepository.php b/app/Contracts/PathsRepository.php
index b1548694..3a291585 100644
--- a/app/Contracts/PathsRepository.php
+++ b/app/Contracts/PathsRepository.php
@@ -10,4 +10,12 @@ interface PathsRepository
      * @return array<int, string>
      */
     public function dirty();
+
+    /**
+     * Determine the files that have changed since branching off from the given branch.
+     *
+     * @param  string  $branch
+     * @return array<int, string>
+     */
+    public function diff($branch);
 }
diff --git a/app/Project.php b/app/Project.php
index 50461c75..f5a5da5c 100644
--- a/app/Project.php
+++ b/app/Project.php
@@ -18,6 +18,10 @@ public static function paths($input)
             return static::resolveDirtyPaths();
         }
 
+        if ($diff = $input->getOption('diff')) {
+            return static::resolveDiffPaths($diff);
+        }
+
         return $input->getArgument('path');
     }
 
@@ -46,4 +50,21 @@ public static function resolveDirtyPaths()
 
         return $files;
     }
+
+    /**
+     * Resolves the paths that have changed since branching off from the given branch, if any.
+     *
+     * @param  string  $branch
+     * @return array<int, string>
+     */
+    public static function resolveDiffPaths($branch)
+    {
+        $files = app(PathsRepository::class)->diff($branch);
+
+        if (empty($files)) {
+            abort(0, "No files have changed since branching off of {$branch}.");
+        }
+
+        return $files;
+    }
 }
diff --git a/app/Repositories/GitPathsRepository.php b/app/Repositories/GitPathsRepository.php
index 37bdc058..d1763b41 100644
--- a/app/Repositories/GitPathsRepository.php
+++ b/app/Repositories/GitPathsRepository.php
@@ -4,6 +4,7 @@
 
 use App\Contracts\PathsRepository;
 use App\Factories\ConfigurationFactory;
+use Illuminate\Support\Collection;
 use Illuminate\Support\Str;
 use Symfony\Component\Process\Process;
 
@@ -41,6 +42,49 @@ public function dirty()
             ->mapWithKeys(fn ($file) => [substr($file, 3) => trim(substr($file, 0, 3))])
             ->reject(fn ($status) => $status === 'D')
             ->map(fn ($status, $file) => $status === 'R' ? Str::after($file, ' -> ') : $file)
+            ->values();
+
+        return $this->processFileNames($dirtyFiles);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function diff($branch)
+    {
+        $files = [
+            'committed' => tap(new Process(['git', 'diff', '--name-only', '--diff-filter=AM', "{$branch}...HEAD", '--', '**.php']))->run(),
+            'staged' => tap(new Process(['git', 'diff', '--name-only', '--diff-filter=AM', '--cached', '--', '**.php']))->run(),
+            'unstaged' => tap(new Process(['git', 'diff', '--name-only', '--diff-filter=AM', '--', '**.php']))->run(),
+            'untracked' => tap(new Process(['git', 'ls-files', '--others', '--exclude-standard', '--', '**.php']))->run(),
+        ];
+
+        $files = collect($files)
+            ->each(fn ($process) => abort_if(
+                boolean: ! $process->isSuccessful(),
+                code: 1,
+                message: 'The [--diff] option is only available when using Git.',
+            ))
+            ->map(fn ($process) => $process->getOutput())
+            ->map(fn ($output) => explode(PHP_EOL, $output))
+            ->flatten()
+            ->filter()
+            ->unique()
+            ->values()
+            ->map(fn ($s) => (string) $s);
+
+        return $this->processFileNames($files);
+    }
+
+    /**
+     * Process the files.
+     *
+     * @param  \Illuminate\Support\Collection<int, string>  $fileNames
+     * @return array<int, string>
+     */
+    protected function processFileNames(Collection $fileNames)
+    {
+        $processedFileNames = $fileNames
             ->map(function ($file) {
                 if (PHP_OS_FAMILY === 'Windows') {
                     $file = str_replace('/', DIRECTORY_SEPARATOR, $file);
@@ -48,7 +92,6 @@ public function dirty()
 
                 return $this->path.DIRECTORY_SEPARATOR.$file;
             })
-            ->values()
             ->all();
 
         $files = array_values(array_map(function ($splFile) {
@@ -58,6 +101,6 @@ public function dirty()
             ->files()
         )));
 
-        return array_values(array_intersect($files, $dirtyFiles));
+        return array_values(array_intersect($files, $processedFileNames));
     }
 }
diff --git a/tests/Feature/DiffTest.php b/tests/Feature/DiffTest.php
new file mode 100644
index 00000000..76b1fcfc
--- /dev/null
+++ b/tests/Feature/DiffTest.php
@@ -0,0 +1,86 @@
+<?php
+
+use App\Contracts\PathsRepository;
+
+it('determines diff files', function () {
+    $paths = Mockery::mock(PathsRepository::class);
+
+    $paths
+        ->shouldReceive('diff')
+        ->with('main')
+        ->once()
+        ->andReturn([
+            base_path('tests/Fixtures/without-issues-laravel/file.php'),
+        ]);
+
+    $this->swap(PathsRepository::class, $paths);
+
+    [$statusCode, $output] = run('default', ['--diff' => 'main']);
+
+    expect($statusCode)->toBe(0)
+        ->and($output)
+        ->toContain('── Laravel', ' 1 file');
+});
+
+it('ignores the path argument', function () {
+    $paths = Mockery::mock(PathsRepository::class);
+
+    $paths
+        ->shouldReceive('diff')
+        ->once()
+        ->andReturn([
+            base_path('tests/Fixtures/without-issues-laravel/file.php'),
+        ]);
+
+    $this->swap(PathsRepository::class, $paths);
+
+    [$statusCode, $output] = run('default', [
+        '--diff' => 'main',
+        'path' => base_path(),
+    ]);
+
+    expect($statusCode)->toBe(0)
+        ->and($output)
+        ->toContain('── Laravel', ' 1 file');
+});
+
+it('does not abort when there are no diff files', function () {
+    $paths = Mockery::mock(PathsRepository::class);
+
+    $paths
+        ->shouldReceive('diff')
+        ->once()
+        ->andReturn([]);
+
+    $this->swap(PathsRepository::class, $paths);
+
+    [$statusCode, $output] = run('default', [
+        '--diff' => 'main',
+    ]);
+
+    expect($statusCode)->toBe(0)
+        ->and($output)
+        ->toContain('── Laravel', ' 0 files');
+});
+
+it('parses nested branch names', function () {
+    $paths = Mockery::mock(PathsRepository::class);
+
+    $paths
+        ->shouldReceive('diff')
+        ->with('origin/main')
+        ->once()
+        ->andReturn([
+            base_path('tests/Fixtures/without-issues-laravel/file.php'),
+        ]);
+
+    $this->swap(PathsRepository::class, $paths);
+
+    [$statusCode, $output] = run('default', [
+        '--diff' => 'origin/main',
+    ]);
+
+    expect($statusCode)->toBe(0)
+        ->and($output)
+        ->toContain('── Laravel', ' 1 file');
+});