Repository: iterative/dvc

Issue:
brancher: yields working tree on clean state
On the description of `brancher` it reads the following:
```
    Yields:
        str: the display name for the currently selected tree, it could be:
            - a git revision identifier
            - empty string it there is no branches to iterate over
            - "Working Tree" if there are uncommited changes in the SCM repo
```

The relevant part is the last one, it should `yield` the "working tree" only if the repository is dirty.
It would be fixed with the following (under `brancher.py`):

```python
    if repo.scm.is_dirty():
        yield "working tree"
```

I think this make sense, because for `dvc metrics show` it is annoying to see the "working tree" when there's no difference from the current branch.


Comments:
@mroutis could you give more context please? 
Sure, @shcheklein , let me edit the description :sweat_smile: . 
@mroutis @Suor  Is this still relevant? There was some dedup optimization in brancher.
@efiop , I'd say it is a priority 3 and more like an enhancement.

```bash
git init
dvc init
dvc run -m foo 'echo 100 > foo'
git add -A
git commit -m "metrics foo"
```

```console
$ dvc metrics show --all-branches
working tree:
	foo: 100
master:
	foo: 100
```

So, the problem is that `working tree` is being returned when you can tell that there's no difference between the current branch and the working tree (because _the HEAD is clean_ -- not sure if I'm using the correct terminology :sweat_smile: )
Other approach is adding "working tree" with a comma, same as dup branches or tags. 
Votes split on priority and whether include it into the next sprint: +1s from @mroutis  and @Suor, -1 from @efiop and @pared. 
Goes as bonus for next sprint if we go well. 
Just discovered that `--all-branches` and friends are noop for `dvc status` when neither `cloud` nor `remote` option is specified. So:
- this issue is only about `metrics show`, other commands don't care
- should fail or show a warning on a noop option use.
@Suor Indeed, it only affects status if `-c` is also specified. So need a group of mutually required (or whatever it is called) flags there. 

Patch:
diff --git a/dvc/repo/metrics/show.py b/dvc/repo/metrics/show.py
--- a/dvc/repo/metrics/show.py
+++ b/dvc/repo/metrics/show.py
@@ -298,6 +298,15 @@ def show(
     if not res and not any(targets):
         raise NoMetricsError()
 
+    # Hide working tree metrics if they are the same as in the active branch
+    try:
+        active_branch = repo.scm.active_branch()
+    except TypeError:
+        pass  # Detached head
+    else:
+        if res.get("working tree") == res.get(active_branch):
+            res.pop("working tree", None)
+
     missing = set(targets) - found
 
     if missing:


Test patch:
diff --git a/tests/func/test_metrics.py b/tests/func/test_metrics.py
--- a/tests/func/test_metrics.py
+++ b/tests/func/test_metrics.py
@@ -83,6 +83,25 @@ def setUp(self):
         self.dvc.scm.checkout("master")
 
 
+def test_show_dirty(tmp_dir, scm, dvc):
+    tmp_dir.gen("metric", "master")
+    dvc.run(metrics_no_cache=["metric"], overwrite=True)
+    tmp_dir.scm_add(["metric", "metric.dvc"], commit="add metric")
+
+    tmp_dir.gen("metric", "dirty")
+
+    assert dvc.metrics.show(["metric"]) == {"": {"metric": "dirty"}}
+
+    assert dvc.metrics.show(["metric"], all_branches=True) == {
+        "working tree": {"metric": "dirty"},
+        "master": {"metric": "master"},
+    }
+
+    assert dvc.metrics.show(["metric"], all_tags=True) == {
+        "working tree": {"metric": "dirty"}
+    }
+
+
 class TestMetrics(TestMetricsBase):
     def test_show(self):
         ret = self.dvc.metrics.show(["metric"], all_branches=True)
@@ -708,7 +727,6 @@ def _test_metrics(self, func):
                 "master": {"metrics.json": ["master"]},
                 "one": {"metrics.json": ["one"]},
                 "two": {"metrics.json": ["two"]},
-                "working tree": {"metrics.json": ["two"]},
             },
         )
 
@@ -722,7 +740,6 @@ def _test_metrics(self, func):
                 "master": {"metrics.json": ["master"]},
                 "one": {"metrics.json": ["one"]},
                 "two": {"metrics.json": ["two"]},
-                "working tree": {"metrics.json": ["two"]},
             },
         )