diff --git a/src/Shift/Parsers.hs b/src/Shift/Parsers.hs
index 4a74084d5817883f60eab2da414a79980fef27c2..3e8b57939e4fa21102d378346af20f0463678998 100644
--- a/src/Shift/Parsers.hs
+++ b/src/Shift/Parsers.hs
@@ -29,7 +29,6 @@ import Text.Megaparsec
     choice,
     many,
     manyTill,
-    skipMany,
     skipSome,
     some,
     someTill,
@@ -62,13 +61,9 @@ conventionalCommit = do
   cType <- commitType
   cScope <- optional (char '(' *> someCharsTill (try $ char ')'))
   void $ string ": "
-  cSubject <- someCharsTill (choice [eol >> pure (), eof])
+  cSubject <- someCharsTill (choice [void eol, eof])
 
-  cBody <- spaced . manyCharsTill . lookAhead $ do
-    skipMany (try breakingChange)
-    skipMany (try ticketChange)
-    _ <- many eol
-    eof
+  cBody <- spaced commitBody
 
   cBreakingChanges <- many (try breakingChange)
   cTicketChanges <- many (try ticketChange)
@@ -111,6 +106,13 @@ commitType = do
     "chore" -> CTChore
     _ -> CTFeature
 
+commitBody :: Parser String
+commitBody = manyCharsTill sectionEnd
+  where
+    sectionEnd = try (spaced eof) <|> lookAheadToBreakingChange <|> lookAheadToTicketChange
+    lookAheadToBreakingChange = try . void $ lookAhead (spaced breakingChange)
+    lookAheadToTicketChange = try . void $ lookAhead (spaced ticketChange)
+
 breakingChange :: Parser BreakingChange
 breakingChange = do
   void . spaced . string $ "BREAKING CHANGE: "
diff --git a/test/Test/Shift/ParsersSpec.hs b/test/Test/Shift/ParsersSpec.hs
index 5dfc19e99365a11a5ae77d562194fd507c965690..c0a86416be2ac9032c63d6bc1819d744b52f9ff8 100644
--- a/test/Test/Shift/ParsersSpec.hs
+++ b/test/Test/Shift/ParsersSpec.hs
@@ -108,6 +108,26 @@ spec = do
                               _ccAffectedTickets = []
                             }
                       )
+    it "parses a conventional commit with a body" $ do
+      parse
+        commit
+        ""
+        "feat(Git): Render empty changelogs\n\
+        \\n\
+        \Adds support for empty diffs. Instead of throwing/erroring out, `shift` will\n\
+        \now render an empty changelog when the diff between two refs is empty.\n"
+        `shouldParse` ( PCConventional $
+                          ConventionalCommit
+                            { _ccType = CTFeature,
+                              _ccScope = Just "Git",
+                              _ccSubject = "Render empty changelogs",
+                              _ccBody =
+                                "Adds support for empty diffs. Instead of throwing/erroring out, `shift` will\n\
+                                \now render an empty changelog when the diff between two refs is empty.",
+                              _ccBreakingChanges = [],
+                              _ccAffectedTickets = []
+                            }
+                      )
     it "parses a conventional commit with breaking changes and a body" $ do
       parse
         commit
@@ -164,4 +184,4 @@ spec = do
                                     ]
                                 ]
                             }
-                      )
\ No newline at end of file
+                      )