Repository: iterative/dvc

Issue:
`data status`: update cli hints
What I'd suggest here is to change the hint in "not in cache" to always use `fetch` (maybe some specialization for no cache with `dvc pull`), and then for uncommitted changes, we can show two hints like how git does:

```console
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
```
```console
  (use "dvc commit <file>..." to track changes)
  (use "dvc checkout <file>..." to restore changes)
```

There are some questionable behaviours in checkout, so it may not always work without `--force`, but that should be fixed separately, and in checkout itself.

_Originally posted by @skshetry in https://github.com/iterative/dvc/issues/8170#issuecomment-1227310120_


Discussion:

Resolving patch:
diff --git a/dvc/commands/data.py b/dvc/commands/data.py
--- a/dvc/commands/data.py
+++ b/dvc/commands/data.py
@@ -31,14 +31,22 @@ class CmdDataStatus(CmdBase):
         "unchanged": "DVC unchanged files",
     }
     HINTS = {
-        "not_in_cache": 'use "dvc pull <file>..." to download files',
-        "committed": "git commit the corresponding dvc files "
-        "to update the repo",
-        "uncommitted": 'use "dvc commit <file>..." to track changes',
-        "untracked": 'use "git add <file> ..." or '
-        'dvc add <file>..." to commit to git or to dvc',
-        "git_dirty": "there are {}changes not tracked by dvc, "
-        'use "git status" to see',
+        "not_in_cache": ('use "dvc fetch <file>..." to download files',),
+        "committed": (
+            "git commit the corresponding dvc files to update the repo",
+        ),
+        "uncommitted": (
+            'use "dvc commit <file>..." to track changes',
+            'use "dvc checkout <file>..." to discard changes',
+        ),
+        "untracked": (
+            'use "git add <file> ..." or '
+            'dvc add <file>..." to commit to git or to dvc',
+        ),
+        "git_dirty": (
+            "there are {}changes not tracked by dvc, "
+            'use "git status" to see',
+        ),
     }
 
     @staticmethod
@@ -75,8 +83,9 @@ def _show_status(cls, status: "DataStatus") -> int:
             color = cls.COLORS.get(stage, None)
 
             ui.write(header)
-            if hint := cls.HINTS.get(stage):
-                ui.write(f"  ({hint})")
+            if hints := cls.HINTS.get(stage):
+                for hint in hints:
+                    ui.write(f"  ({hint})")
 
             if isinstance(stage_status, dict):
                 items = [
@@ -91,9 +100,10 @@ def _show_status(cls, status: "DataStatus") -> int:
                 out = "\n".join(tabs + item for item in chunk)
                 ui.write(colorize(out, color))
 
-        if (hint := cls.HINTS.get("git_dirty")) and git_info.get("is_dirty"):
-            message = hint.format("other " if result else "")
-            ui.write(f"[blue]({message})[/]", styled=True)
+        if (hints := cls.HINTS.get("git_dirty")) and git_info.get("is_dirty"):
+            for hint in hints:
+                message = hint.format("other " if result else "")
+                ui.write(f"[blue]({message})[/]", styled=True)
         return 0
 
     def run(self) -> int:


Test patch:
diff --git a/tests/unit/command/test_data_status.py b/tests/unit/command/test_data_status.py
--- a/tests/unit/command/test_data_status.py
+++ b/tests/unit/command/test_data_status.py
@@ -110,7 +110,7 @@ def test_show_status(dvc, scm, mocker, capsys, mocked_status, args, is_dirty):
     out, err = capsys.readouterr()
     expected_out = """\
 Not in cache:
-  (use "dvc pull <file>..." to download files)
+  (use "dvc fetch <file>..." to download files)
         notincache
 
 DVC committed changes:
@@ -123,6 +123,7 @@ def test_show_status(dvc, scm, mocker, capsys, mocked_status, args, is_dirty):
 
 DVC uncommitted changes:
   (use "dvc commit <file>..." to track changes)
+  (use "dvc checkout <file>..." to discard changes)
         added: dir/baz
         modified: dir/bar
         deleted: dir/foobar