diff --git a/src/Shift/Git.hs b/src/Shift/Git.hs
index c0c9afa7f074b92231a422f994c51fbb68cb06df..11b849a6d3e6687630342ed563e4f5c3677320c7 100644
--- a/src/Shift/Git.hs
+++ b/src/Shift/Git.hs
@@ -7,7 +7,6 @@ module Shift.Git where
 
 import CMarkGFM (Node (Node), NodeType (DOCUMENT))
 import Control.Lens ((^.))
-import Control.Monad.Catch (throwM)
 import Control.Monad.Reader (runReaderT)
 import Control.Monad.State (runStateT)
 import Control.Monad.Trans (liftIO)
@@ -168,7 +167,7 @@ renderDiff repo (tx, ty) = do
   diff <- lookupCommitsDiff repo tx ty
 
   case diff of
-    [] -> throwM SEUnableToComputeDiff
+    [] -> printReport (tx, ty) def
     diff_ -> printReport (tx, ty) (generateReport . rights $ parseCommit <$> diff_)
 
 lookupCommitsDiff ::
diff --git a/src/Shift/Rendering.hs b/src/Shift/Rendering.hs
index c9e2f89588cae989d384d136cc0910d80a4ff757..839fa9ee90fa9d3aeffbe430d27f2894842a61b6 100644
--- a/src/Shift/Rendering.hs
+++ b/src/Shift/Rendering.hs
@@ -10,9 +10,10 @@ import Control.Monad.IO.Class (MonadIO)
 import Control.Monad.State (MonadState)
 import Control.Monad.Trans.Writer (execWriterT)
 import Control.Monad.Trans.Writer.Lazy (tell)
+import Data.Default (Default (def))
 import Data.Git (Commit, Ref, RefName (refNameRaw), commitAuthor)
 import Data.List (sortOn)
-import Data.Maybe (fromMaybe, fromMaybe, catMaybes)
+import Data.Maybe (catMaybes, fromMaybe)
 import Data.String.Conversions (cs)
 import Data.Text (Text)
 import qualified Data.Text as T (pack, take)
@@ -202,21 +203,25 @@ printReport ::
 printReport (rangeStart, rangeEnd) report = execWriterT $ do
   tell [headerOne $ renderRange rangeStart rangeEnd]
 
-  -- Print conventional commits
-  conventionalSection "New features:" crFeatures
-  conventionalSection "Fixes:" crFixes
-  conventionalSection "Updated documentation:" crDocs
-  conventionalSection "Refactors:" crRefactors
-  conventionalSection "Updated tests:" crTests
-  conventionalSection "Style fixes:" crStyles
-  conventionalSection "Chores:" crChores
-
-  -- Print miscs and merges
-  miscCommits <- mapM renderMiscCommit (report ^. crMisc)
-  mergeCommits <- mapM renderMergeCommit (report ^. crMerges)
-
-  textSection "Miscellaneous changes:" miscCommits
-  textSection "Merge commits:" mergeCommits
+  -- If the report is empty, don't render any changes.
+  if report == def
+    then tell [paragraphNode [textNode "No changes"]]
+    else do
+      -- Print conventional commits
+      conventionalSection "New features:" crFeatures
+      conventionalSection "Fixes:" crFixes
+      conventionalSection "Updated documentation:" crDocs
+      conventionalSection "Refactors:" crRefactors
+      conventionalSection "Updated tests:" crTests
+      conventionalSection "Style fixes:" crStyles
+      conventionalSection "Chores:" crChores
+
+      -- Print miscs and merges
+      miscCommits <- mapM renderMiscCommit (report ^. crMisc)
+      mergeCommits <- mapM renderMergeCommit (report ^. crMerges)
+
+      textSection "Miscellaneous changes:" miscCommits
+      textSection "Merge commits:" mergeCommits
   where
     conventionalSection label sectionLens = do
       let rawCommits = sortOn (\(_, _, pc) -> pc ^. ccScope) (report ^. sectionLens)
diff --git a/src/Shift/Types.hs b/src/Shift/Types.hs
index 69f745de8654a46c8ab7775f2d272a2f7df52097..6a32e5b5d791578eeb5225d362dfdee63febedd7 100644
--- a/src/Shift/Types.hs
+++ b/src/Shift/Types.hs
@@ -149,7 +149,7 @@ data ChangeReport hash = ChangeReport
     _crBreakingChanges :: [BreakingChange],
     _crAffectedTickets :: HashSet TicketChange
   }
-  deriving (Show)
+  deriving (Show, Eq)
 
 instance Default (ChangeReport hash) where
   def =