Repository: iterative/dvc

Issue:
exp run: include new staged files
              > Related: if I `git add` an untracked file, I would like it to be included in the experiment

@dberenbaum let's create a separate issue for that, as it is a different problem.

For the record, a staged new file gets included in `--tmp` / `--queue` experiments but not in workspace ones.

_Originally posted by @daavoo in https://github.com/iterative/dvc/issues/6297#issuecomment-1424046082_
            


Discussion:

Resolving patch:
diff --git a/dvc/repo/experiments/__init__.py b/dvc/repo/experiments/__init__.py
--- a/dvc/repo/experiments/__init__.py
+++ b/dvc/repo/experiments/__init__.py
@@ -96,19 +96,9 @@ def stash_revs(self) -> Dict[str, "ExpStashEntry"]:
     def reproduce_one(
         self,
         tmp_dir: bool = False,
-        machine: Optional[str] = None,
         **kwargs,
     ):
         """Reproduce and checkout a single (standalone) experiment."""
-        if not (tmp_dir or machine):
-            staged, _, _ = self.scm.status(untracked_files="no")
-            if staged:
-                logger.warning(
-                    "Your workspace contains staged Git changes which will be "
-                    "unstaged before running this experiment."
-                )
-                self.scm.reset()
-
         exp_queue: "BaseStashQueue" = (
             self.tempdir_queue if tmp_dir else self.workspace_queue
         )
diff --git a/dvc/repo/experiments/queue/base.py b/dvc/repo/experiments/queue/base.py
--- a/dvc/repo/experiments/queue/base.py
+++ b/dvc/repo/experiments/queue/base.py
@@ -323,12 +323,12 @@ def _stash_exp(  # noqa: C901
         .. _Hydra Override:
             https://hydra.cc/docs/next/advanced/override_grammar/basic/
         """
-        with self.scm.detach_head(client="dvc") as orig_head:
-            stash_head = orig_head
-            if baseline_rev is None:
-                baseline_rev = orig_head
+        with self.scm.stash_workspace(reinstate_index=True) as workspace:
+            with self.scm.detach_head(client="dvc") as orig_head:
+                stash_head = orig_head
+                if baseline_rev is None:
+                    baseline_rev = orig_head
 
-            with self.scm.stash_workspace() as workspace:
                 try:
                     if workspace:
                         self.stash.apply(workspace)


Test patch:
diff --git a/tests/func/experiments/test_stash_exp.py b/tests/func/experiments/test_stash_exp.py
new file mode 100644
--- /dev/null
+++ b/tests/func/experiments/test_stash_exp.py
@@ -0,0 +1,70 @@
+import logging
+
+import pytest
+from funcy import first
+
+from dvc.exceptions import ReproductionError
+
+
+@pytest.mark.parametrize("tmp", [True, False])
+@pytest.mark.parametrize("staged", [True, False])
+def test_deleted(tmp_dir, scm, dvc, caplog, tmp, staged):
+    if not tmp:
+        pytest.xfail("TODO: https://github.com/iterative/dvc/issues/6297")
+
+    tmp_dir.scm_gen("file", "file", commit="commit file")
+    stage = dvc.stage.add(
+        cmd="cat file",
+        name="foo",
+    )
+    scm.add_commit(["dvc.yaml"], message="add dvc.yaml")
+
+    file = tmp_dir / "file"
+    file.unlink()
+    if staged:
+        scm.add(["file"])
+
+    with caplog.at_level(logging.ERROR):
+        with pytest.raises(ReproductionError):
+            dvc.experiments.run(stage.addressing, tmp_dir=tmp)
+        assert "failed to reproduce 'foo'" in caplog.text
+
+    assert not file.exists()
+
+
+@pytest.mark.parametrize("tmp", [True, False])
+@pytest.mark.parametrize("staged", [True, False])
+def test_modified(tmp_dir, scm, dvc, caplog, tmp, staged):
+    tmp_dir.scm_gen("file", "file", commit="commit file")
+    stage = dvc.stage.add(
+        cmd="cat file",
+        name="foo",
+    )
+    scm.add_commit(["dvc.yaml"], message="add dvc.yaml")
+
+    (tmp_dir / "file").write_text("modified_file")
+    if staged:
+        scm.add(["file"])
+
+    results = dvc.experiments.run(stage.addressing, tmp_dir=tmp)
+
+    exp = first(results)
+    scm.checkout(exp, force=True)
+    assert (tmp_dir / "file").read_text() == "modified_file"
+
+
+@pytest.mark.parametrize("tmp", [True, False])
+def test_staged_new_file(tmp_dir, scm, dvc, tmp):
+    stage = dvc.stage.add(
+        cmd="cat file",
+        name="foo",
+    )
+    scm.add_commit(["dvc.yaml"], message="add dvc.yaml")
+
+    (tmp_dir / "file").write_text("file")
+    scm.add(["file"])
+
+    results = dvc.experiments.run(stage.addressing, tmp_dir=tmp)
+    exp = first(results)
+    fs = scm.get_fs(exp)
+    assert fs.exists("file")