Use a commit graph to represent commit history internally

Just looping over the commits checking the commit messages for merges
doesn't support all scenarios (including the relatively common scenario
of commits being pushed directly to the repository) and doesn't provide
access to the commit structure for better formatting and understanding
the changes made.

This only builds the graph and updates things to only look at the first
parents rather than looking at every commit.  In general, this will only
make a difference in the case of "nested" merges like this:
```
* This commit will still be checked but not included - it's not a merge.
* This commit will be included - it's a first parent and is a merge.
|\
| * This one will no longer be included - it's a merge, but "nested".
| |\
| | * This one was never included - not a merge
| |/
| * This one was never included - not a merge
|/
* This is the base tag, i.e., part of the last release, and not included
```

This will begin to provide the structure necessary to:
* Handle non-merge commits without pulling in all commits.  Previously,
  trying to support commits would mean that even commits that were part
  of a merge/PR would also have been included in the release notes even
  though the merge/PR was already there.  Now that we can differentiate
  between direct pushes and commits (only direct pushes are "first
  parents"), we can include all commits that are first parents in the
  release notes.
* Enable viewing full commit history of merges.  When prompting the user
  for how to represent pull requests in the release notes, sometimes
  needing more info on the individual commits is needed.  The merge
  commit itself may not have a descriptive message and does not have
  code changes directly associated.  By parsing the commit graph, this
  enables us to determine the righthand commits that made up the merge
  and present them all to the user for review.
* Enable splitting up a merge into its constituent pieces.  As above,
  the graph structure will allow us to enter into a sub-structure to
  handle nested commits/merges.  Sometimes a single merge may actually
  include multiple changes, and we can now provide the user the ability
  to access these changes separately and categorize them correctly in
  the final release notes.
* Support proper issue relationships.  We can search through the full
  commit history of merges in order to find mentions of issues to link
  to in the release notes.