diff --git a/dvc/dependency/base.py b/dvc/dependency/base.py
index 246bc75b0..525e40209 100644
--- a/dvc/dependency/base.py
+++ b/dvc/dependency/base.py
@@ -11,11 +11,6 @@ class DependencyError(DvcException):
         super(DependencyError, self).__init__('Dependency \'{}\' error: {}'.format(path, msg))
 
 
-class DependencyOutsideOfRepoError(DependencyError):
-    def __init__(self, path):
-        super(DependencyOutsideOfRepoError, self).__init__(path, 'outside of repository')
-
-
 class DependencyDoesNotExistError(DependencyError):
     def __init__(self, path):
         super(DependencyDoesNotExistError, self).__init__(path, 'does not exist')
diff --git a/dvc/dependency/local.py b/dvc/dependency/local.py
index 4fdb3e8fa..081ae81e6 100644
--- a/dvc/dependency/local.py
+++ b/dvc/dependency/local.py
@@ -3,6 +3,11 @@ import schema
 import posixpath
 import ntpath
 
+try:
+    from urlparse import urlparse
+except ImportError:
+    from urllib.parse import urlparse
+
 from dvc.dependency.base import *
 from dvc.logger import Logger
 from dvc.utils import remove
@@ -20,12 +25,17 @@ class DependencyLOCAL(DependencyBase):
     def __init__(self, stage, path, info=None, remote=None):
         self.stage = stage
         self.project = stage.project
+        self.info = info
+        self.remote = remote if remote != None else RemoteLOCAL(stage.project, {})
+
+        if remote:
+            path = os.path.join(remote.prefix, urlparse(path).path.lstrip('/'))
+
         if not os.path.isabs(path):
-            path = self.unixpath(path)
+            path = self.ospath(path)
             path = os.path.join(stage.cwd, path)
         self.path = os.path.normpath(path)
-        self.info = info
-        self.remote = remote if remote != None else RemoteLOCAL(stage.project, {})
+
         self.path_info = {'scheme': 'local',
                           'path': self.path}
 
@@ -54,12 +64,23 @@ class DependencyLOCAL(DependencyBase):
 
         self.info = self.remote.save_info(self.path_info)
 
+    def ospath(self, path):
+        if os.name == 'nt':
+            return self.ntpath(path)
+        return self.unixpath(path)
+
     @staticmethod
     def unixpath(path):
         assert not ntpath.isabs(path)
         assert not posixpath.isabs(path)
         return path.replace('\\', '/')
 
+    @staticmethod
+    def ntpath(path):
+        assert not ntpath.isabs(path)
+        assert not posixpath.isabs(path)
+        return path.replace('/', '\\')
+
     def dumpd(self):
         if self.path.startswith(self.stage.project.root_dir):
             path = self.unixpath(os.path.relpath(self.path, self.stage.cwd))
diff --git a/dvc/output/local.py b/dvc/output/local.py
index e36ec20e0..53e62e31f 100644
--- a/dvc/output/local.py
+++ b/dvc/output/local.py
@@ -66,10 +66,16 @@ class OutputLOCAL(DependencyLOCAL):
             self.project.logger.debug(msg.format(self.rel_path))
             return
 
-        if self.project.scm.is_tracked(self.path):
-            raise OutputAlreadyTrackedError(self.rel_path)
+        if self.path.startswith(self.project.root_dir):
+            if self.project.scm.is_tracked(self.path):
+                raise OutputAlreadyTrackedError(self.rel_path)
+
+            if self.use_cache:
+                self.project.scm.ignore(self.path)
 
         self.info = self.project.cache.local.save(self.path_info)
 
-    def remove(self):
+    def remove(self, ignore_remove=False):
         self.remote.remove(self.path_info)
+        if ignore_remove and self.use_cache:
+            self.project.scm.ignore_remove(self.path)
diff --git a/dvc/remote/local.py b/dvc/remote/local.py
index a30d625b1..38901c215 100644
--- a/dvc/remote/local.py
+++ b/dvc/remote/local.py
@@ -35,6 +35,10 @@ class RemoteLOCAL(RemoteBase):
 
         self.state = State(self.cache_dir)
 
+    @property
+    def prefix(self):
+        return self.cache_dir
+
     def all(self):
         clist = []
         for entry in os.listdir(self.cache_dir):
diff --git a/dvc/stage.py b/dvc/stage.py
index d1f658526..231677923 100644
--- a/dvc/stage.py
+++ b/dvc/stage.py
@@ -115,14 +115,12 @@ class Stage(object):
 
         return ret
 
-    def remove_outs(self):
+    def remove_outs(self, ignore_remove=False):
         for out in self.outs:
-            out.remove()
-            if out.use_cache:
-                self.project.scm.ignore_remove(out.path)
+            out.remove(ignore_remove=ignore_remove)
 
     def remove(self):
-        self.remove_outs()
+        self.remove_outs(ignore_remove=True)
         os.unlink(self.path)
 
     def reproduce(self, force=False):
@@ -131,7 +129,7 @@ class Stage(object):
 
         if self.cmd:
             # Removing outputs only if we actually have command to reproduce
-            self.remove_outs()
+            self.remove_outs(ignore_remove=False)
 
         self.run()
 
@@ -223,8 +221,6 @@ class Stage(object):
 
         for out in self.outs:
             out.save()
-            if out.use_cache and out.path_info['scheme'] == 'local':
-                self.project.scm.ignore(out.path)
 
     def run(self):
         if not self.is_data_source:

Support external local deps/outputs
We currently support external local cache, but deps/outs are not yet supported. Adding support for that should be pretty trivial, since a lot of infrastructure already exists for other types.

See https://discuss.dvc.org/t/shared-cache-directory/
diff --git a/tests/test_repro.py b/tests/test_repro.py
index cfc823dca..ff55fc1c0 100644
--- a/tests/test_repro.py
+++ b/tests/test_repro.py
@@ -3,6 +3,7 @@ import yaml
 import stat
 import shutil
 import filecmp
+import tempfile
 from subprocess import Popen, PIPE
 
 import boto3
@@ -222,31 +223,47 @@ class TestReproExternalBase(TestDvc):
     def should_test(self):
         return False
 
+    @property
+    def cache_scheme(self):
+        return self.scheme
+
+    @property
+    def scheme(self):
+        return None
+
+    @property
+    def scheme_sep(self):
+        return '://'
+
+    @property
+    def sep(self):
+        return '/'
+
     def test(self):
         if not self.should_test():
             return
 
-        cache = self.scheme + '://' + self.bucket + '/' + str(uuid.uuid4())
+        cache = self.scheme + self.scheme_sep + self.bucket + self.sep + str(uuid.uuid4())
 
-        ret = main(['config', 'cache.' + self.scheme, 'myrepo'])
+        ret = main(['config', 'cache.' + self.cache_scheme, 'myrepo'])
         self.assertEqual(ret, 0)
         ret = main(['remote', 'add', 'myrepo', cache])
         self.assertEqual(ret, 0)
 
         remote_name = 'myremote'
         remote_key = str(uuid.uuid4())
-        remote = self.scheme + '://' + self.bucket + '/' + remote_key
+        remote = self.scheme + self.scheme_sep + self.bucket + self.sep + remote_key
 
         ret = main(['remote', 'add', remote_name, remote])
         self.assertEqual(ret, 0)
 
         self.dvc = Project('.')
 
-        foo_key = remote_key + '/' + self.FOO
-        bar_key = remote_key + '/' + self.BAR
+        foo_key = remote_key + self.sep + self.FOO
+        bar_key = remote_key + self.sep + self.BAR
 
-        foo_path = self.scheme + '://' + self.bucket + '/' + foo_key
-        bar_path = self.scheme + '://' + self.bucket + '/' + bar_key
+        foo_path = self.scheme + self.scheme_sep + self.bucket + self.sep + foo_key
+        bar_path = self.scheme + self.scheme_sep + self.bucket + self.sep + bar_key
 
         # Using both plain and remote notation
         out_foo_path = 'remote://' + remote_name + '/' + self.FOO
@@ -351,6 +368,51 @@ class TestReproExternalHDFS(TestReproExternalBase):
         self.assertEqual(p.returncode, 0)
 
  
+class TestReproExternalLOCAL(TestReproExternalBase):
+    def setUp(self):
+        super(TestReproExternalLOCAL, self).setUp()
+        self.tmpdir = tempfile.mkdtemp()
+
+    def should_test(self):
+        return True
+
+    @property
+    def cache_scheme(self):
+        return 'local'
+
+    @property
+    def scheme(self):
+        return ''
+
+    @property
+    def scheme_sep(self):
+        return ''
+
+    @property
+    def sep(self):
+        return os.sep
+
+    @property
+    def bucket(self):
+        return self.tmpdir
+
+    @property
+    def cmd(self):
+        if os.name == 'nt':
+            return 'copy'
+        return 'cp'
+
+    def write(self, bucket, key, body):
+        path = os.path.join(bucket, key)
+        dname = os.path.dirname(path)
+
+        if not os.path.exists(dname):
+            os.makedirs(dname)
+
+        with open(path, 'w+') as fd:
+            fd.write(body)
+
+
 class TestReproShell(TestDvc):
     def test(self):
         if os.name == 'nt':

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cov
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
altgraph==0.17.4
bcrypt==4.3.0
binaryornot==0.4.4
boto3==1.7.4
botocore==1.10.84
cachetools==4.2.4
certifi==2025.1.31
cffi==1.17.1
chardet==5.2.0
charset-normalizer==3.4.1
colorama==0.4.6
configobj==5.0.9
configparser==7.2.0
coverage==7.8.0
cryptography==44.0.2
decorator==5.2.1
dill==0.2.9
docutils==0.21.2
-e git+https://github.com/iterative/dvc.git@5ea2fd8367b678b38ef699b479f385e401dbaf85#egg=dvc
exceptiongroup==1.2.2
future==0.16.0
gapic-google-cloud-datastore-v1==0.15.3
gapic-google-cloud-error-reporting-v1beta1==0.15.3
gapic-google-cloud-logging-v2==0.91.3
gitdb==4.0.12
GitPython==3.1.44
google-api-core==0.1.4
google-auth==1.35.0
google-cloud==0.32.0
google-cloud-bigquery==0.28.0
google-cloud-bigquery-datatransfer==0.1.1
google-cloud-bigtable==0.28.1
google-cloud-container==0.1.1
google-cloud-core==0.28.1
google-cloud-datastore==1.4.0
google-cloud-dns==0.28.0
google-cloud-error-reporting==0.28.0
google-cloud-firestore==0.28.0
google-cloud-language==1.0.2
google-cloud-logging==1.4.0
google-cloud-monitoring==0.28.1
google-cloud-pubsub==0.30.1
google-cloud-resource-manager==0.28.1
google-cloud-runtimeconfig==0.28.1
google-cloud-spanner==0.29.0
google-cloud-speech==0.30.0
google-cloud-storage==1.6.0
google-cloud-trace==0.17.0
google-cloud-translate==1.3.1
google-cloud-videointelligence==1.0.1
google-cloud-vision==0.29.0
google-crc32c==1.7.1
google-gax==0.15.16
google-resumable-media==2.7.2
googleapis-common-protos==1.69.2
grpc-google-iam-v1==0.11.4
grpcio==1.71.0
httplib2==0.22.0
idna==3.10
iniconfig==2.1.0
jmespath==0.10.0
jsonpath-rw==1.4.0
macholib==1.16.3
nanotime==0.5.2
networkx==3.2.1
ntfsutils==0.1.5
oauth2client==3.0.0
packaging==24.2
paramiko==3.5.1
pefile==2024.8.26
pluggy==1.5.0
ply==3.8
proto-google-cloud-datastore-v1==0.90.4
proto-google-cloud-error-reporting-v1beta1==0.15.3
proto-google-cloud-logging-v2==0.91.3
protobuf==3.20.3
psutil==5.9.8
pyasn1==0.6.1
pyasn1_modules==0.4.2
pycparser==2.22
PyInstaller==3.3.1
PyNaCl==1.5.0
pyparsing==3.2.3
pytest==8.3.5
pytest-cov==6.0.0
python-dateutil==2.9.0.post0
pytz==2025.2
PyYAML==6.0.2
reflink==0.2.0
requests==2.32.3
rsa==4.9
s3transfer==0.1.13
schema==0.7.7
six==1.17.0
smmap==5.0.2
tomli==2.2.1
urllib3==2.3.0
zc.lockfile==3.0.post1

name: dvc
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:
      - altgraph==0.17.4
      - bcrypt==4.3.0
      - binaryornot==0.4.4
      - boto3==1.7.4
      - botocore==1.10.84
      - cachetools==4.2.4
      - certifi==2025.1.31
      - cffi==1.17.1
      - chardet==5.2.0
      - charset-normalizer==3.4.1
      - colorama==0.4.6
      - configobj==5.0.9
      - configparser==7.2.0
      - coverage==7.8.0
      - cryptography==44.0.2
      - decorator==5.2.1
      - dill==0.2.9
      - docutils==0.21.2
      - exceptiongroup==1.2.2
      - future==0.16.0
      - gapic-google-cloud-datastore-v1==0.15.3
      - gapic-google-cloud-error-reporting-v1beta1==0.15.3
      - gapic-google-cloud-logging-v2==0.91.3
      - gitdb==4.0.12
      - gitpython==3.1.44
      - google-api-core==0.1.4
      - google-auth==1.35.0
      - google-cloud==0.32.0
      - google-cloud-bigquery==0.28.0
      - google-cloud-bigquery-datatransfer==0.1.1
      - google-cloud-bigtable==0.28.1
      - google-cloud-container==0.1.1
      - google-cloud-core==0.28.1
      - google-cloud-datastore==1.4.0
      - google-cloud-dns==0.28.0
      - google-cloud-error-reporting==0.28.0
      - google-cloud-firestore==0.28.0
      - google-cloud-language==1.0.2
      - google-cloud-logging==1.4.0
      - google-cloud-monitoring==0.28.1
      - google-cloud-pubsub==0.30.1
      - google-cloud-resource-manager==0.28.1
      - google-cloud-runtimeconfig==0.28.1
      - google-cloud-spanner==0.29.0
      - google-cloud-speech==0.30.0
      - google-cloud-storage==1.6.0
      - google-cloud-trace==0.17.0
      - google-cloud-translate==1.3.1
      - google-cloud-videointelligence==1.0.1
      - google-cloud-vision==0.29.0
      - google-crc32c==1.7.1
      - google-gax==0.15.16
      - google-resumable-media==2.7.2
      - googleapis-common-protos==1.69.2
      - grpc-google-iam-v1==0.11.4
      - grpcio==1.71.0
      - httplib2==0.22.0
      - idna==3.10
      - iniconfig==2.1.0
      - jmespath==0.10.0
      - jsonpath-rw==1.4.0
      - macholib==1.16.3
      - nanotime==0.5.2
      - networkx==3.2.1
      - ntfsutils==0.1.5
      - oauth2client==3.0.0
      - packaging==24.2
      - paramiko==3.5.1
      - pefile==2024.8.26
      - pluggy==1.5.0
      - ply==3.8
      - proto-google-cloud-datastore-v1==0.90.4
      - proto-google-cloud-error-reporting-v1beta1==0.15.3
      - proto-google-cloud-logging-v2==0.91.3
      - protobuf==3.20.3
      - psutil==5.9.8
      - pyasn1==0.6.1
      - pyasn1-modules==0.4.2
      - pycparser==2.22
      - pyinstaller==3.3.1
      - pynacl==1.5.0
      - pyparsing==3.2.3
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - pyyaml==6.0.2
      - reflink==0.2.0
      - requests==2.32.3
      - rsa==4.9
      - s3transfer==0.1.13
      - schema==0.7.7
      - six==1.17.0
      - smmap==5.0.2
      - tomli==2.2.1
      - urllib3==2.3.0
      - zc-lockfile==3.0.post1
prefix: /opt/conda/envs/dvc

tests/test_repro.py::TestReproExternalLOCAL::test
tests/test_repro.py::TestReproMissingMd5InStageFile::test tests/test_repro.py::TestReproShell::test
tests/test_repro.py::TestReproNoDeps::test tests/test_repro.py::TestReproForce::test tests/test_repro.py::TestReproChangedCode::test tests/test_repro.py::TestReproChangedData::test tests/test_repro.py::TestReproChangedDeepData::test tests/test_repro.py::TestReproPhony::test tests/test_repro.py::TestNonExistingOutput::test tests/test_repro.py::TestReproDataSource::test tests/test_repro.py::TestReproChangedDir::test tests/test_repro.py::TestCmdRepro::test tests/test_repro.py::TestCmdReproChdir::test tests/test_repro.py::TestReproExternalBase::test tests/test_repro.py::TestReproExternalS3::test tests/test_repro.py::TestReproExternalGS::test tests/test_repro.py::TestReproExternalHDFS::test
dvc/stage.py dvc/output/local.py dvc/remote/local.py dvc/dependency/local.py dvc/dependency/base.py
dvc/stage.py dvc/output/local.py dvc/remote/local.py dvc/dependency/local.py dvc/dependency/base.py