diff --git a/CHANGELOG.md b/CHANGELOG.md
index acbcc3b..7159c48 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,7 @@
 ## Devel
 
+- Print informative message if `git` is not installed
+
 ## 1.1.1
 
 - Fixed `get` failing to clone new repos with error `Remote branch ['master'] not found in upstream origin`
diff --git a/assigner/__init__.py b/assigner/__init__.py
index 1099245..b19db23 100755
--- a/assigner/__init__.py
+++ b/assigner/__init__.py
@@ -6,6 +6,7 @@ import sys
 
 from colorlog import ColoredFormatter
 from requests.exceptions import HTTPError
+from git.cmd import GitCommandNotFound
 
 from assigner.baserepo import StudentRepo
 from assigner.config import config_context
@@ -186,6 +187,8 @@ def main(args=sys.argv[1:]):
             raise e
         if isinstance(e, KeyError):
             logger.error("%s is missing", e)
+        elif isinstance(e, GitCommandNotFound):
+            logger.error("git is not installed!")
         else:
             logger.error(str(e))
         raise SystemExit(1) from e

Assigner doesn't provide a helpful message if git is not installed
...instead, assigner yells at you in an unsettling manner!

I will provide an example later today.
diff --git a/assigner/tests/assigner_test.py b/assigner/tests/assigner_test.py
index 2811a70..771e70e 100644
--- a/assigner/tests/assigner_test.py
+++ b/assigner/tests/assigner_test.py
@@ -4,6 +4,8 @@ from unittest.mock import patch
 from assigner import main, make_parser, subcommands
 from assigner.tests.utils import AssignerTestCase
 
+from git.cmd import GitCommandNotFound
+
 
 class MakeParserTestCase(AssignerTestCase):
     def setUp(self):
@@ -134,6 +136,22 @@ class MainTestCase(AssignerTestCase):
             "%s is missing", self.mock_args.run.side_effect
         )
 
+    @patch("assigner.logger", autospec=True)
+    def test_main_logs_gitcommandnotfound_with_catch(self, mock_logger):
+        """
+        main should log a GitCommandNotFound with "git is not installed!" when raised.
+        """
+        self.mock_args.tracebacks = False
+        self.mock_args.run.side_effect = GitCommandNotFound()
+        try:
+            main([])
+        except SystemExit:
+            pass
+
+        mock_logger.error.assert_called_once_with(
+            "git is not installed!"
+        )
+
     def test_main_sets_verbosity(self):
         """
         main should set verosity and level from args.

pip install -e .
parse_log_pytest
requirements.txt
pytest
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
-e git+https://github.com/redkyn/assigner.git@2c0c0b34ce80e776eeaf18e8028a0821513131b1#egg=assigner
astroid==1.6.6
attrs==22.2.0
certifi==2021.5.30
colorlog==2.6.0
gitdb==0.6.4
GitPython==1.0.1
importlib-metadata==4.8.3
iniconfig==1.1.1
isort==5.10.1
jsonschema==2.5.1
lazy-object-proxy==1.7.1
mccabe==0.3.1
nose==1.3.7
nose-parameterized==0.6.0
packaging==21.3
pep8==1.5.7
pluggy==1.0.0
progressbar2==3.10.1
PTable==0.9.2
py==1.11.0
pyapi-gitlab==7.8.5
pyflakes==1.0.0
pylint==1.8.1
pyparsing==3.1.4
pytest==7.0.1
python-utils==2.2.0
PyYAML==3.11
requests==2.9.1
setuptools-scm==1.15.7
six==1.10.0
smmap==0.9.0
tomli==1.2.3
tqdm==4.19.5
typing_extensions==4.1.1
wrapt==1.10.11
zipp==3.6.0

name: assigner
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
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - 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
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - astroid==1.6.6
      - attrs==22.2.0
      - colorlog==2.6.0
      - gitdb==0.6.4
      - gitpython==1.0.1
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - isort==5.10.1
      - jsonschema==2.5.1
      - lazy-object-proxy==1.7.1
      - mccabe==0.3.1
      - nose==1.3.7
      - nose-parameterized==0.6.0
      - packaging==21.3
      - pep8==1.5.7
      - pluggy==1.0.0
      - progressbar2==3.10.1
      - ptable==0.9.2
      - py==1.11.0
      - pyapi-gitlab==7.8.5
      - pyflakes==1.0.0
      - pylint==1.8.1
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-utils==2.2.0
      - pyyaml==3.11
      - requests==2.9.1
      - setuptools-scm==1.15.7
      - six==1.10.0
      - smmap==0.9.0
      - tomli==1.2.3
      - tqdm==4.19.5
      - typing-extensions==4.1.1
      - wheel==0.24.0
      - wrapt==1.10.11
      - zipp==3.6.0
prefix: /opt/conda/envs/assigner

assigner/tests/assigner_test.py::MainTestCase::test_main_logs_gitcommandnotfound_with_catch
assigner/tests/assigner_test.py::MakeParserTestCase::test_add_default_help assigner/tests/assigner_test.py::MakeParserTestCase::test_adds_all_subcommands assigner/tests/assigner_test.py::MakeParserTestCase::test_creates_argument_parser assigner/tests/assigner_test.py::MainTestCase::test_calls_args_run assigner/tests/assigner_test.py::MainTestCase::test_calls_make_parser assigner/tests/assigner_test.py::MainTestCase::test_main_catches_exceptions assigner/tests/assigner_test.py::MainTestCase::test_main_logs_exceptions assigner/tests/assigner_test.py::MainTestCase::test_main_logs_keyerror_with_catch assigner/tests/assigner_test.py::MainTestCase::test_main_raises_exceptions_with_traceback assigner/tests/assigner_test.py::MainTestCase::test_main_sets_verbosity
assigner/__init__.py CHANGELOG.md
assigner/__init__.py CHANGELOG.md