diff --git a/pre_commit/commands/run.py b/pre_commit/commands/run.py
index c18f2aa..55d2b12 100644
--- a/pre_commit/commands/run.py
+++ b/pre_commit/commands/run.py
@@ -217,7 +217,7 @@ def _has_unstaged_config(runner):
 
 
 def run(runner, args, environ=os.environ):
-    no_stash = args.no_stash or args.all_files or bool(args.files)
+    no_stash = args.all_files or bool(args.files)
 
     # Check if we have unresolved merge conflict files and fail fast.
     if _has_unmerged_paths(runner):
@@ -227,20 +227,11 @@ def run(runner, args, environ=os.environ):
         logger.error('Specify both --origin and --source.')
         return 1
     if _has_unstaged_config(runner) and not no_stash:
-        if args.allow_unstaged_config:
-            logger.warn(
-                'You have an unstaged config file and have specified the '
-                '--allow-unstaged-config option.\n'
-                'Note that your config will be stashed before the config is '
-                'parsed unless --no-stash is specified.',
-            )
-        else:
-            logger.error(
-                'Your .pre-commit-config.yaml is unstaged.\n'
-                '`git add .pre-commit-config.yaml` to fix this.\n'
-                'Run pre-commit with --allow-unstaged-config to silence this.',
-            )
-            return 1
+        logger.error(
+            'Your .pre-commit-config.yaml is unstaged.\n'
+            '`git add .pre-commit-config.yaml` to fix this.\n',
+        )
+        return 1
 
     # Expose origin / source as environment variables for hooks to consume
     if args.origin and args.source:
diff --git a/pre_commit/main.py b/pre_commit/main.py
index 3a2fee1..0b00a86 100644
--- a/pre_commit/main.py
+++ b/pre_commit/main.py
@@ -135,10 +135,6 @@ def main(argv=None):
     _add_color_option(run_parser)
     _add_config_option(run_parser)
     run_parser.add_argument('hook', nargs='?', help='A single hook-id to run')
-    run_parser.add_argument(
-        '--no-stash', default=False, action='store_true',
-        help='Use this option to prevent auto stashing of unstaged files.',
-    )
     run_parser.add_argument(
         '--verbose', '-v', action='store_true', default=False,
     )
@@ -154,13 +150,6 @@ def main(argv=None):
         '--commit-msg-filename',
         help='Filename to check when running during `commit-msg`',
     )
-    run_parser.add_argument(
-        '--allow-unstaged-config', default=False, action='store_true',
-        help=(
-            'Allow an unstaged config to be present.  Note that this will '
-            'be stashed before parsing unless --no-stash is specified.'
-        ),
-    )
     run_parser.add_argument(
         '--hook-stage', choices=('commit', 'push', 'commit-msg'),
         default='commit',
@@ -173,7 +162,7 @@ def main(argv=None):
     run_mutex_group = run_parser.add_mutually_exclusive_group(required=False)
     run_mutex_group.add_argument(
         '--all-files', '-a', action='store_true', default=False,
-        help='Run on all the files in the repo.  Implies --no-stash.',
+        help='Run on all the files in the repo.',
     )
     run_mutex_group.add_argument(
         '--files', nargs='*', default=[],

Deprecate and remove some (useless?) options
I find the following don't really have any good use cases (and don't come up in normal day-to-day) and are undocumented beyond `--help`.  **I'm proposing removing these options**:

## `pre-commit run --no-stash`

This disables the auto-stashing of files when running -- though this is already the case for `pre-commit run --all-files` and `pre-commit run --files ...`.

The behaviour of `--no-stash` (without using `--no-stash`) can be achieved via `git diff --name-only | xargs pre-commit run --files`

It was added [along with the avoiding behaviour](https://github.com/pre-commit/pre-commit/pull/80) in the same pull request.  I want to say this was my first idea for "fixing" the [original problem](https://github.com/pre-commit/pre-commit/issues/68) and then I forgot to undo it.

## `pre-commit run --allow-unstaged-config`

This (unfortunately) collides with `pre-commit run --all` (prefix match of `pre-commit run --all-files`) so I've wanted to get rid of it anyway.

This allows one to run with an unstaged configuration, which then (in most cases) gets the changes swiped out from under you and causes confusing situations where the hooks that are run aren't what was on disk at the time of running.  The warning that's printed when doing this also explains this.

This was [originally my idea](https://github.com/pre-commit/pre-commit/issues/157#issuecomment-99080756) but now I think we can just do without the option at all -- requiring the pre-commit configuration to be staged when running pre-commit.
diff --git a/tests/commands/run_test.py b/tests/commands/run_test.py
index c360fde..924d097 100644
--- a/tests/commands/run_test.py
+++ b/tests/commands/run_test.py
@@ -54,10 +54,8 @@ def _get_opts(
         color=False,
         verbose=False,
         hook=None,
-        no_stash=False,
         origin='',
         source='',
-        allow_unstaged_config=False,
         hook_stage='commit',
         show_diff_on_failure=False,
         commit_msg_filename='',
@@ -70,10 +68,8 @@ def _get_opts(
         color=color,
         verbose=verbose,
         hook=hook,
-        no_stash=no_stash,
         origin=origin,
         source=source,
-        allow_unstaged_config=allow_unstaged_config,
         hook_stage=hook_stage,
         show_diff_on_failure=show_diff_on_failure,
         commit_msg_filename=commit_msg_filename,
@@ -332,38 +328,6 @@ def test_origin_source_error_msg(
         assert warning_msg not in printed
 
 
-@pytest.mark.parametrize(
-    ('no_stash', 'all_files', 'expect_stash'),
-    (
-        (True, True, False),
-        (True, False, False),
-        (False, True, False),
-        (False, False, True),
-    ),
-)
-def test_no_stash(
-        cap_out,
-        repo_with_passing_hook,
-        no_stash,
-        all_files,
-        expect_stash,
-        mock_out_store_directory,
-):
-    stage_a_file()
-    # Make unstaged changes
-    with open('foo.py', 'w') as foo_file:
-        foo_file.write('import os\n')
-
-    args = _get_opts(no_stash=no_stash, all_files=all_files)
-    ret, printed = _do_run(cap_out, repo_with_passing_hook, args)
-    assert ret == 0
-    warning_msg = b'[WARNING] Unstaged files detected.'
-    if expect_stash:
-        assert warning_msg in printed
-    else:
-        assert warning_msg not in printed
-
-
 @pytest.mark.parametrize(('output', 'expected'), (('some', True), ('', False)))
 def test_has_unmerged_paths(output, expected):
     mock_runner = mock.Mock()
@@ -715,37 +679,19 @@ def modified_config_repo(repo_with_passing_hook):
     yield repo_with_passing_hook
 
 
-def test_allow_unstaged_config_option(
+def test_error_with_unstaged_config(
         cap_out, modified_config_repo, mock_out_store_directory,
 ):
-    args = _get_opts(allow_unstaged_config=True)
-    ret, printed = _do_run(cap_out, modified_config_repo, args)
-    expected = (
-        b'You have an unstaged config file and have specified the '
-        b'--allow-unstaged-config option.'
-    )
-    assert expected in printed
-    assert ret == 0
-
-
-def test_no_allow_unstaged_config_option(
-        cap_out, modified_config_repo, mock_out_store_directory,
-):
-    args = _get_opts(allow_unstaged_config=False)
+    args = _get_opts()
     ret, printed = _do_run(cap_out, modified_config_repo, args)
     assert b'Your .pre-commit-config.yaml is unstaged.' in printed
     assert ret == 1
 
 
 @pytest.mark.parametrize(
-    'opts',
-    (
-        {'allow_unstaged_config': False, 'no_stash': True},
-        {'all_files': True},
-        {'files': [C.CONFIG_FILE]},
-    ),
+    'opts', ({'all_files': True}, {'files': [C.CONFIG_FILE]}),
 )
-def test_unstaged_message_suppressed(
+def test_no_unstaged_error_with_all_files_or_files(
         cap_out, modified_config_repo, mock_out_store_directory, opts,
 ):
     args = _get_opts(**opts)
diff --git a/tests/git_test.py b/tests/git_test.py
index 4ffccee..0500a42 100644
--- a/tests/git_test.py
+++ b/tests/git_test.py
@@ -137,8 +137,7 @@ def test_get_conflicted_files_in_submodule(in_conflicting_submodule):
 
 
 def test_get_conflicted_files_unstaged_files(in_merge_conflict):
-    # If they for whatever reason did pre-commit run --no-stash during a
-    # conflict
+    """This case no longer occurs, but it is a useful test nonetheless"""
     resolve_conflict()
 
     # Make unstaged file.

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.9
requirements-dev.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
aspy.yaml==1.3.0
cached-property==2.0.1
coverage==7.8.0
distlib==0.3.9
exceptiongroup==1.2.2
filelock==3.18.0
flake8==7.2.0
identify==2.6.9
iniconfig==2.1.0
mccabe==0.7.0
mock==5.2.0
nodeenv==1.9.1
packaging==24.2
platformdirs==4.3.7
pluggy==1.5.0
-e git+https://github.com/pre-commit/pre-commit.git@7139a47c1ca968a2699e467279677fa77ad68aae#egg=pre_commit
pycodestyle==2.13.0
pyflakes==3.3.1
pytest==8.3.5
pytest-env==1.1.5
PyYAML==6.0.2
six==1.17.0
tomli==2.2.1
virtualenv==20.29.3

name: pre-commit
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - aspy-yaml==1.3.0
      - cached-property==2.0.1
      - coverage==7.8.0
      - distlib==0.3.9
      - exceptiongroup==1.2.2
      - filelock==3.18.0
      - flake8==7.2.0
      - identify==2.6.9
      - iniconfig==2.1.0
      - mccabe==0.7.0
      - mock==5.2.0
      - nodeenv==1.9.1
      - packaging==24.2
      - platformdirs==4.3.7
      - pluggy==1.5.0
      - pycodestyle==2.13.0
      - pyflakes==3.3.1
      - pytest==8.3.5
      - pytest-env==1.1.5
      - pyyaml==6.0.2
      - six==1.17.0
      - tomli==2.2.1
      - virtualenv==20.29.3
prefix: /opt/conda/envs/pre-commit

tests/commands/run_test.py::test_run_all_hooks_failing tests/commands/run_test.py::test_hook_that_modifies_but_returns_zero tests/commands/run_test.py::test_types_hook_repository tests/commands/run_test.py::test_exclude_types_hook_repository tests/commands/run_test.py::test_show_diff_on_failure tests/commands/run_test.py::test_run[options0-outputs0-0-True] tests/commands/run_test.py::test_run[options1-outputs1-0-True] tests/commands/run_test.py::test_run[options2-outputs2-0-True] tests/commands/run_test.py::test_run[options3-outputs3-1-True] tests/commands/run_test.py::test_run[options4-outputs4-0-True] tests/commands/run_test.py::test_run[options5-outputs5-0-True] tests/commands/run_test.py::test_run[options6-outputs6-0-False] tests/commands/run_test.py::test_run_output_logfile tests/commands/run_test.py::test_always_run tests/commands/run_test.py::test_always_run_alt_config tests/commands/run_test.py::test_origin_source_error_msg[master-master-False] tests/commands/run_test.py::test_origin_source_error_msg[master--True] tests/commands/run_test.py::test_origin_source_error_msg[-master-True] tests/commands/run_test.py::test_merge_conflict tests/commands/run_test.py::test_merge_conflict_modified tests/commands/run_test.py::test_merge_conflict_resolved tests/commands/run_test.py::test_skip_hook tests/commands/run_test.py::test_hook_id_not_in_non_verbose_output tests/commands/run_test.py::test_hook_id_in_verbose_output tests/commands/run_test.py::test_multiple_hooks_same_id tests/commands/run_test.py::test_push_hook tests/commands/run_test.py::test_commit_msg_hook tests/commands/run_test.py::test_local_hook_passes tests/commands/run_test.py::test_local_hook_fails tests/commands/run_test.py::test_error_with_unstaged_config tests/commands/run_test.py::test_no_unstaged_error_with_all_files_or_files[opts0] tests/commands/run_test.py::test_no_unstaged_error_with_all_files_or_files[opts1] tests/commands/run_test.py::test_pass_filenames[True-hook_args0-foo.py] tests/commands/run_test.py::test_pass_filenames[False-hook_args1-] tests/commands/run_test.py::test_pass_filenames[True-hook_args2-some tests/commands/run_test.py::test_pass_filenames[False-hook_args3-some
tests/commands/run_test.py::test_arbitrary_bytes_hook tests/commands/run_test.py::test_hook_install_failure
tests/commands/run_test.py::test_has_unmerged_paths[some-True] tests/commands/run_test.py::test_has_unmerged_paths[-False] tests/commands/run_test.py::test_compute_cols[hooks0-True-80] tests/commands/run_test.py::test_compute_cols[hooks1-False-81] tests/commands/run_test.py::test_compute_cols[hooks2-True-85] tests/commands/run_test.py::test_compute_cols[hooks3-False-82] tests/commands/run_test.py::test_get_skips[environ0-expected_output0] tests/commands/run_test.py::test_get_skips[environ1-expected_output1] tests/commands/run_test.py::test_get_skips[environ2-expected_output2] tests/commands/run_test.py::test_get_skips[environ3-expected_output3] tests/commands/run_test.py::test_get_skips[environ4-expected_output4] tests/commands/run_test.py::test_get_skips[environ5-expected_output5] tests/commands/run_test.py::test_get_skips[environ6-expected_output6] tests/commands/run_test.py::test_non_ascii_hook_id tests/commands/run_test.py::test_stdout_write_bug_py26 tests/commands/run_test.py::test_get_changed_files tests/commands/run_test.py::test_lots_of_files tests/commands/run_test.py::test_files_running_subdir tests/git_test.py::test_get_root_at_root tests/git_test.py::test_get_root_deeper tests/git_test.py::test_get_root_not_git_dir tests/git_test.py::test_get_staged_files_deleted tests/git_test.py::test_is_not_in_merge_conflict tests/git_test.py::test_is_in_merge_conflict tests/git_test.py::test_cherry_pick_conflict tests/git_test.py::test_get_files_matching_base tests/git_test.py::test_matches_broken_symlink tests/git_test.py::test_get_files_matching_total_match tests/git_test.py::test_does_search_instead_of_match tests/git_test.py::test_does_not_include_deleted_fileS tests/git_test.py::test_exclude_removes_files tests/git_test.py::test_get_conflicted_files tests/git_test.py::test_get_conflicted_files_unstaged_files tests/git_test.py::test_parse_merge_msg_for_conflicts[Merge
pre_commit/main.py pre_commit/commands/run.py
pre_commit/main.py pre_commit/commands/run.py