We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`exp run`: data gets re-imported on every call
# Bug Report

## Description

When a pipeline uses an imported data file (with `dvc import`), the data gets cloned(?) and hashed every time `dvc exp run` is called.

### Reproduce

1. dvc import git@github.com:iterative/dataset-registry.git use-cases/cats-dogs
2. dvc stage add -n foo -d cats-dogs echo foo
3. dvc exp run

### Expected

When using `dvc repro` the imported data doesn't get re-hashed. I would expect `dvc exp run` to behave the same.

### Environment information

**Output of `dvc doctor`:**

```console
$ dvc doctor
DVC version: 2.6.3 (pip)
---------------------------------
Platform: Python 3.9.6 on macOS-10.16-x86_64-i386-64bit
Supports:
        gdrive (pydrive2 = 1.9.1),
        http (requests = 2.26.0),
        https (requests = 2.26.0)
Cache types: reflink, hardlink, symlink
Cache directory: apfs on /dev/disk1s1s1
Caches: local
Remotes: None
Workspace directory: apfs on /dev/disk1s1s1
Repo: dvc, git
```

**Additional Information (if any):**

```console
$ dvc repro -v
2021-08-25 11:11:55,186 DEBUG: Computed stage: 'cats-dogs.dvc' md5: '5a135b297ee3c96465ce4b320f44fb8b'
'cats-dogs.dvc' didn't change, skipping
Stage 'foo' didn't change, skipping
Data and pipelines are up to date.
```

```console
$ dvc exp run -v
2021-08-25 11:12:15,672 DEBUG: Detaching HEAD at 'HEAD'               
2021-08-25 11:12:15,690 DEBUG: Stashing workspace
2021-08-25 11:12:15,700 DEBUG: No changes to stash
2021-08-25 11:12:15,749 DEBUG: Creating external repo git@github.com:iterative/dataset-registry.git@ca140591a21c6d75a7057d1e2eb3f51d3115c5f5
2021-08-25 11:12:15,749 DEBUG: erepo: git clone 'git@github.com:iterative/dataset-registry.git' to a temporary dir
Computing file/dir hashes (only done once)  
. . .                                                                         
```



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `dvc/repo/commit.py`
Content:
```
1 from dvc import prompt
2 
3 from . import locked
4 
5 
6 def _prepare_message(stage, changes):
7     changed_deps, changed_outs, changed_stage = changes
8     if changed_deps and changed_outs:
9         msg = "dependencies {deps} and outputs {outs} of {stage} changed."
10     elif changed_deps:
11         msg = "dependencies {deps} of {stage} changed."
12     elif changed_outs:
13         msg = "outputs {outs} of {stage} changed."
14     else:
15         msg = "{stage_changed}"
16 
17     msg += " Are you sure you want to commit it?"
18 
19     kw = {
20         "stage": stage,
21         "deps": changed_deps,
22         "outs": changed_outs,
23         "stage_changed": changed_stage,
24     }
25     return msg.format_map(kw)
26 
27 
28 def prompt_to_commit(stage, changes, force=False):
29     from dvc.stage.exceptions import StageCommitError
30 
31     if not (force or prompt.confirm(_prepare_message(stage, changes))):
32         raise StageCommitError(
33             "unable to commit changed {}. Use `-f|--force` to "
34             "force.".format(stage)
35         )
36 
37 
38 @locked
39 def commit(
40     self,
41     target,
42     with_deps=False,
43     recursive=False,
44     force=False,
45     allow_missing=False,
46     data_only=False,
47 ):
48     from dvc.dvcfile import Dvcfile
49 
50     stages_info = [
51         info
52         for info in self.stage.collect_granular(
53             target, with_deps=with_deps, recursive=recursive
54         )
55         if not data_only or info.stage.is_data_source
56     ]
57     for stage_info in stages_info:
58         stage = stage_info.stage
59         changes = stage.changed_entries()
60         if any(changes):
61             prompt_to_commit(stage, changes, force=force)
62             stage.save(allow_missing=allow_missing)
63         stage.commit(
64             filter_info=stage_info.filter_info, allow_missing=allow_missing
65         )
66 
67         Dvcfile(self, stage.path).dump(stage, update_pipeline=False)
68     return [s.stage for s in stages_info]
69
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/dvc/repo/commit.py b/dvc/repo/commit.py
--- a/dvc/repo/commit.py
+++ b/dvc/repo/commit.py
@@ -56,10 +56,13 @@
     ]
     for stage_info in stages_info:
         stage = stage_info.stage
-        changes = stage.changed_entries()
-        if any(changes):
-            prompt_to_commit(stage, changes, force=force)
+        if force:
             stage.save(allow_missing=allow_missing)
+        else:
+            changes = stage.changed_entries()
+            if any(changes):
+                prompt_to_commit(stage, changes, force=force)
+                stage.save(allow_missing=allow_missing)
         stage.commit(
             filter_info=stage_info.filter_info, allow_missing=allow_missing
         )

{"golden_diff": "diff --git a/dvc/repo/commit.py b/dvc/repo/commit.py\n--- a/dvc/repo/commit.py\n+++ b/dvc/repo/commit.py\n@@ -56,10 +56,13 @@\n     ]\n     for stage_info in stages_info:\n         stage = stage_info.stage\n-        changes = stage.changed_entries()\n-        if any(changes):\n-            prompt_to_commit(stage, changes, force=force)\n+        if force:\n             stage.save(allow_missing=allow_missing)\n+        else:\n+            changes = stage.changed_entries()\n+            if any(changes):\n+                prompt_to_commit(stage, changes, force=force)\n+                stage.save(allow_missing=allow_missing)\n         stage.commit(\n             filter_info=stage_info.filter_info, allow_missing=allow_missing\n         )\n", "issue": "`exp run`: data gets re-imported on every call\n# Bug Report\r\n\r\n## Description\r\n\r\nWhen a pipeline uses an imported data file (with `dvc import`), the data gets cloned(?) and hashed every time `dvc exp run` is called.\r\n\r\n### Reproduce\r\n\r\n1. dvc import git@github.com:iterative/dataset-registry.git use-cases/cats-dogs\r\n2. dvc stage add -n foo -d cats-dogs echo foo\r\n3. dvc exp run\r\n\r\n### Expected\r\n\r\nWhen using `dvc repro` the imported data doesn't get re-hashed. I would expect `dvc exp run` to behave the same.\r\n\r\n### Environment information\r\n\r\n**Output of `dvc doctor`:**\r\n\r\n```console\r\n$ dvc doctor\r\nDVC version: 2.6.3 (pip)\r\n---------------------------------\r\nPlatform: Python 3.9.6 on macOS-10.16-x86_64-i386-64bit\r\nSupports:\r\n        gdrive (pydrive2 = 1.9.1),\r\n        http (requests = 2.26.0),\r\n        https (requests = 2.26.0)\r\nCache types: reflink, hardlink, symlink\r\nCache directory: apfs on /dev/disk1s1s1\r\nCaches: local\r\nRemotes: None\r\nWorkspace directory: apfs on /dev/disk1s1s1\r\nRepo: dvc, git\r\n```\r\n\r\n**Additional Information (if any):**\r\n\r\n```console\r\n$ dvc repro -v\r\n2021-08-25 11:11:55,186 DEBUG: Computed stage: 'cats-dogs.dvc' md5: '5a135b297ee3c96465ce4b320f44fb8b'\r\n'cats-dogs.dvc' didn't change, skipping\r\nStage 'foo' didn't change, skipping\r\nData and pipelines are up to date.\r\n```\r\n\r\n```console\r\n$ dvc exp run -v\r\n2021-08-25 11:12:15,672 DEBUG: Detaching HEAD at 'HEAD'               \r\n2021-08-25 11:12:15,690 DEBUG: Stashing workspace\r\n2021-08-25 11:12:15,700 DEBUG: No changes to stash\r\n2021-08-25 11:12:15,749 DEBUG: Creating external repo git@github.com:iterative/dataset-registry.git@ca140591a21c6d75a7057d1e2eb3f51d3115c5f5\r\n2021-08-25 11:12:15,749 DEBUG: erepo: git clone 'git@github.com:iterative/dataset-registry.git' to a temporary dir\r\nComputing file/dir hashes (only done once)  \r\n. . .                                                                         \r\n```\r\n\r\n\n", "before_files": [{"content": "from dvc import prompt\n\nfrom . import locked\n\n\ndef _prepare_message(stage, changes):\n    changed_deps, changed_outs, changed_stage = changes\n    if changed_deps and changed_outs:\n        msg = \"dependencies {deps} and outputs {outs} of {stage} changed.\"\n    elif changed_deps:\n        msg = \"dependencies {deps} of {stage} changed.\"\n    elif changed_outs:\n        msg = \"outputs {outs} of {stage} changed.\"\n    else:\n        msg = \"{stage_changed}\"\n\n    msg += \" Are you sure you want to commit it?\"\n\n    kw = {\n        \"stage\": stage,\n        \"deps\": changed_deps,\n        \"outs\": changed_outs,\n        \"stage_changed\": changed_stage,\n    }\n    return msg.format_map(kw)\n\n\ndef prompt_to_commit(stage, changes, force=False):\n    from dvc.stage.exceptions import StageCommitError\n\n    if not (force or prompt.confirm(_prepare_message(stage, changes))):\n        raise StageCommitError(\n            \"unable to commit changed {}. Use `-f|--force` to \"\n            \"force.\".format(stage)\n        )\n\n\n@locked\ndef commit(\n    self,\n    target,\n    with_deps=False,\n    recursive=False,\n    force=False,\n    allow_missing=False,\n    data_only=False,\n):\n    from dvc.dvcfile import Dvcfile\n\n    stages_info = [\n        info\n        for info in self.stage.collect_granular(\n            target, with_deps=with_deps, recursive=recursive\n        )\n        if not data_only or info.stage.is_data_source\n    ]\n    for stage_info in stages_info:\n        stage = stage_info.stage\n        changes = stage.changed_entries()\n        if any(changes):\n            prompt_to_commit(stage, changes, force=force)\n            stage.save(allow_missing=allow_missing)\n        stage.commit(\n            filter_info=stage_info.filter_info, allow_missing=allow_missing\n        )\n\n        Dvcfile(self, stage.path).dump(stage, update_pipeline=False)\n    return [s.stage for s in stages_info]\n", "path": "dvc/repo/commit.py"}], "after_files": [{"content": "from dvc import prompt\n\nfrom . import locked\n\n\ndef _prepare_message(stage, changes):\n    changed_deps, changed_outs, changed_stage = changes\n    if changed_deps and changed_outs:\n        msg = \"dependencies {deps} and outputs {outs} of {stage} changed.\"\n    elif changed_deps:\n        msg = \"dependencies {deps} of {stage} changed.\"\n    elif changed_outs:\n        msg = \"outputs {outs} of {stage} changed.\"\n    else:\n        msg = \"{stage_changed}\"\n\n    msg += \" Are you sure you want to commit it?\"\n\n    kw = {\n        \"stage\": stage,\n        \"deps\": changed_deps,\n        \"outs\": changed_outs,\n        \"stage_changed\": changed_stage,\n    }\n    return msg.format_map(kw)\n\n\ndef prompt_to_commit(stage, changes, force=False):\n    from dvc.stage.exceptions import StageCommitError\n\n    if not (force or prompt.confirm(_prepare_message(stage, changes))):\n        raise StageCommitError(\n            \"unable to commit changed {}. Use `-f|--force` to \"\n            \"force.\".format(stage)\n        )\n\n\n@locked\ndef commit(\n    self,\n    target,\n    with_deps=False,\n    recursive=False,\n    force=False,\n    allow_missing=False,\n    data_only=False,\n):\n    from dvc.dvcfile import Dvcfile\n\n    stages_info = [\n        info\n        for info in self.stage.collect_granular(\n            target, with_deps=with_deps, recursive=recursive\n        )\n        if not data_only or info.stage.is_data_source\n    ]\n    for stage_info in stages_info:\n        stage = stage_info.stage\n        if force:\n            stage.save(allow_missing=allow_missing)\n        else:\n            changes = stage.changed_entries()\n            if any(changes):\n                prompt_to_commit(stage, changes, force=force)\n                stage.save(allow_missing=allow_missing)\n        stage.commit(\n            filter_info=stage_info.filter_info, allow_missing=allow_missing\n        )\n\n        Dvcfile(self, stage.path).dump(stage, update_pipeline=False)\n    return [s.stage for s in stages_info]\n", "path": "dvc/repo/commit.py"}]}