diff --git a/emanate/__init__.py b/emanate/__init__.py
index 173ccaa..38e1faa 100644
--- a/emanate/__init__.py
+++ b/emanate/__init__.py
@@ -111,9 +111,13 @@ class Emanate:
         in the destination directory.
         """
         path = str(path_obj.absolute())
-        ignore_patterns = [
-            p / "*" if Emanate._is_dir(p) else p for p in self.config.ignore
-        ]
+        ignore_patterns = []
+        for pattern in self.config.ignore:
+            ignore_patterns.append(pattern)
+            # If it's a directory, also ignore its contents.
+            if Emanate._is_dir(pattern):
+                ignore_patterns.append(pattern / "*")
+
         if any(fnmatch(path, str(pattern)) for pattern in ignore_patterns):
             return False
 

Empty `~/.git/` despite `.git/` being ignored.
This appears to be caused by `emanate.Emanate.valid_file()`: https://github.com/duckinator/emanate/blob/master/emanate/__init__.py#L107-L125

It looks like it doesn't match the directory itself, only things in it. I think the definition of `ignore_patterns` would need to be changed to fix this.
diff --git a/tests/test_integration.py b/tests/test_integration.py
index 940c1db..0721465 100644
--- a/tests/test_integration.py
+++ b/tests/test_integration.py
@@ -88,6 +88,9 @@ def test_empty_config():
                 'src': {
                     'foo': '',
                     'emanate.json': '{}',
+                    '.git': {
+                        'a': 'b',
+                    },
                 },
                 'dest': {},
             },
@@ -95,6 +98,8 @@ def test_empty_config():
     ):
         assert (tmpdir / 'dest' / 'foo').samefile(tmpdir / 'src'  / 'foo')
         assert not (tmpdir / 'dest'  / 'emanate.json').exists()
+        # This catches issue #144.
+        assert not (tmpdir / 'dest'  / '.git').exists()
 
 
 def test_clean():

pip install -e .[dev]
parse_log_pytest
pytest
pytest
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///croot/attrs_1668696182826/work
certifi @ file:///croot/certifi_1671487769961/work/certifi
-e git+https://github.com/duckinator/emanate.git@51a0d38c3d10044141ef82251c4129dcc7deab02#egg=emanate
flit_core @ file:///opt/conda/conda-bld/flit-core_1644941570762/work/source/flit_core
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1648562407465/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
packaging @ file:///croot/packaging_1671697413597/work
pluggy @ file:///tmp/build/80754af9/pluggy_1648042572264/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pytest==7.1.2
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
typing_extensions @ file:///croot/typing_extensions_1669924550328/work
zipp @ file:///croot/zipp_1672387121353/work

name: emanate
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
  - attrs=22.1.0=py37h06a4308_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - flit-core=3.6.0=pyhd3eb1b0_0
  - importlib-metadata=4.11.3=py37h06a4308_0
  - importlib_metadata=4.11.3=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_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=1.1.1w=h7f8727e_0
  - packaging=22.0=py37h06a4308_0
  - pip=22.3.1=py37h06a4308_0
  - pluggy=1.0.0=py37h06a4308_1
  - py=1.11.0=pyhd3eb1b0_0
  - pytest=7.1.2=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py37h06a4308_0
  - typing_extensions=4.4.0=py37h06a4308_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.11.0=py37h06a4308_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - emanate==7.0.0
prefix: /opt/conda/envs/emanate

tests/test_integration.py::test_empty_config
tests/test_integration.py::test_config_relative_path tests/test_integration.py::test_no_config tests/test_integration.py::test_clean
emanate/__init__.py
emanate/__init__.py