diff --git a/commandline.go b/commandline.go
index 364a74d58e0133391ab57ee1944fd6c4bc76d124..c9baea3b1a0151c7db4a23db5d95923d2d5146d8 100644
--- a/commandline.go
+++ b/commandline.go
@@ -6,6 +6,8 @@ import (
 	"time"
 
 	"github.com/jessevdk/go-flags"
+
+	"github.com/go-git/go-git/v5"
 )
 
 var (
@@ -65,12 +67,16 @@ func increaseMajor() (string, error) {
 	return next.String(), nil
 }
 
+var gitRepo *git.Repository
+
 func executeCommand() {
 
 	arguments = new(commandLineOptions)
 	p := flags.NewParser(arguments, flags.Default)
 
-	_, err := p.Parse()
+	var err error
+
+	_, err = p.Parse()
 	if err != nil {
 		os.Exit(-1)
 	}
@@ -83,8 +89,17 @@ func executeCommand() {
 
 	var newVersion string
 	command := activeCommand.Name
+
+	if arguments.Git || command == "auto" {
+		gitRepo, err = git.PlainOpen(".")
+		if err != nil {
+			fmt.Println(err)
+			os.Exit(-1)
+		}
+	}
+
 	if command == "auto" {
-		updateType, err := GetCommitType(".")
+		updateType, err := GetCommitType(gitRepo)
 		if err != nil {
 			fmt.Println(err)
 			os.Exit(-1)
@@ -108,13 +123,13 @@ func executeCommand() {
 	switch command {
 	case "print":
 		if arguments.Git {
-			version, err := getLatestSemanticTag(".")
+			version, err := getLatestSemanticTag(gitRepo)
 			if err != nil {
 				fmt.Println(err)
 				os.Exit(-1)
 			}
 
-			fmt.Printf("%s", version)
+			fmt.Printf("%s", version.String())
 			os.Exit(0)
 		}
 	case "date":
diff --git a/git.go b/git.go
index 84c29d9c192678e1e652d8e9d437043b3855d2e5..d6a19c313346de76b2bce7073a49100933a9ca48 100644
--- a/git.go
+++ b/git.go
@@ -2,17 +2,51 @@ package main
 
 import (
 	"fmt"
-	"strings"
-
 	"regexp"
 	"sort"
 	"strconv"
+	"strings"
 
 	"github.com/go-git/go-git/v5"
 	"github.com/go-git/go-git/v5/plumbing"
 	"github.com/go-git/go-git/v5/plumbing/object"
+	"github.com/go-git/go-git/v5/plumbing/storer"
 )
 
+var versionRegex = regexp.MustCompile(`^v?(\d+)\.(\d+)\.(\d+).*$`)
+
+type SemanticVersion struct {
+	Major int
+	Minor int
+	Patch int
+	Tag   string
+}
+
+func (v SemanticVersion) String() string {
+	return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
+}
+
+func ParseSemanticVersion(tag string) SemanticVersion {
+	matches := versionRegex.FindStringSubmatch(tag)
+	major, _ := strconv.Atoi(matches[1])
+	minor, _ := strconv.Atoi(matches[2])
+	patch, _ := strconv.Atoi(matches[3])
+	return SemanticVersion{major, minor, patch, tag}
+}
+
+func (v SemanticVersion) IsLessThan(w SemanticVersion) bool {
+	if v.Major != w.Major {
+		return v.Major < w.Major
+	}
+	if v.Minor != w.Minor {
+		return v.Minor < w.Minor
+	}
+	if v.Patch != w.Patch {
+		return v.Patch < w.Patch
+	}
+	return false
+}
+
 type CommitType int
 
 const (
@@ -22,13 +56,14 @@ const (
 	FixCommit
 )
 
-func GetCommitType(path string) (CommitType, error) {
-	r, err := git.PlainOpen(path)
+func GetCommitType(r *git.Repository) (CommitType, error) {
+
+	latestTag, err := getLatestSemanticTag(r)
 	if err != nil {
-		return OtherCommit, fmt.Errorf("failed to open repository: %v", err)
+		return OtherCommit, err
 	}
 
-	tagCommit, err := getLatestTagCommit(r)
+	tagCommit, err := getTagCommit(r, latestTag.Tag)
 	if err != nil {
 		return OtherCommit, err
 	}
@@ -41,109 +76,62 @@ func GetCommitType(path string) (CommitType, error) {
 	return commitType, nil
 }
 
-func getLatestSemanticTag(path string) (string, error) {
-	r, err := git.PlainOpen(path)
-	if err != nil {
-		return "", fmt.Errorf("failed to open repository: %v", err)
-	}
-
+func getLatestSemanticTag(r *git.Repository) (SemanticVersion, error) {
 	tagList, err := getSemanticTags(r)
 	if err != nil {
-		return "", err
+		return SemanticVersion{}, err
 	}
 
 	if len(tagList) == 0 {
-		return "", fmt.Errorf("no semantic tags found")
+		return SemanticVersion{}, fmt.Errorf("no semantic tags found")
 	}
 
-	sort.Slice(tagList, func(i, j int) bool {
-		return compareSemanticVersions(tagList[i], tagList[j])
-	})
-
 	return tagList[len(tagList)-1], nil
 }
 
-func getSemanticTags(r *git.Repository) ([]string, error) {
+func getTagCommit(r *git.Repository, tag string) (*object.Commit, error) {
 	tags, err := r.Tags()
 	if err != nil {
 		return nil, fmt.Errorf("failed to get tags: %v", err)
 	}
 
-	var tagList []string
-	err = tags.ForEach(func(tag *plumbing.Reference) error {
-		tagName := tag.Name().Short()
-		if isSemanticVersion(tagName) {
-			tagList = append(tagList, tagName)
+	var tagCommit *object.Commit
+	err = tags.ForEach(func(t *plumbing.Reference) error {
+		if t.Name().Short() == tag {
+			tagObj, err := r.TagObject(t.Hash())
+			if err != nil {
+				return err
+			}
+			tagCommit, err = tagObj.Commit()
+			if err != nil {
+				return err
+			}
+			return storer.ErrStop // stop iteration
 		}
 		return nil
 	})
-
 	if err != nil {
 		return nil, fmt.Errorf("failed to iterate over tags: %v", err)
 	}
-
-	return tagList, nil
-}
-
-func isSemanticVersion(tagName string) bool {
-	versionRegex := regexp.MustCompile(`^v?\d+\.\d+\.\d+.*$`)
-	return versionRegex.MatchString(tagName)
-}
-
-func compareSemanticVersions(a, b string) bool {
-	// Remove leading "v" if present
-	a = strings.TrimPrefix(a, "v")
-	b = strings.TrimPrefix(b, "v")
-
-	aParts := strings.Split(a, ".")
-	bParts := strings.Split(b, ".")
-
-	for i := 0; i < len(aParts) && i < len(bParts); i++ {
-		aNum, _ := strconv.Atoi(aParts[i])
-		bNum, _ := strconv.Atoi(bParts[i])
-
-		if aNum != bNum {
-			return aNum < bNum
-		}
+	if tagCommit == nil {
+		return nil, fmt.Errorf("tag commit not found in commit log")
 	}
 
-	return len(aParts) < len(bParts)
+	return tagCommit, nil
 }
 
-func getLatestTagCommit(r *git.Repository) (*object.Commit, error) {
+func getSemanticTags(r *git.Repository) ([]SemanticVersion, error) {
 	tags, err := r.Tags()
 	if err != nil {
 		return nil, fmt.Errorf("failed to get tags: %v", err)
 	}
 
-	var mostRecentTag *plumbing.Reference
-	var mostRecentCommit *object.Commit
-
+	var tagList []SemanticVersion
 	err = tags.ForEach(func(tag *plumbing.Reference) error {
-		obj, err := r.TagObject(tag.Hash())
-		if err != nil {
-			if err == plumbing.ErrObjectNotFound {
-				// If the tag object is not found, it's likely a lightweight tag pointing directly to a commit
-				commit, err := r.CommitObject(tag.Hash())
-				if err != nil {
-					return err
-				}
-				obj = &object.Tag{Tagger: commit.Author, Message: commit.Message}
-			} else {
-				return err
-			}
-		}
-
-		commit, err := obj.Commit()
-		if err != nil {
-			return err
-		}
-
-		if mostRecentTag == nil || commit.Committer.When.After(mostRecentCommit.Committer.When) {
-			mostRecentTag = tag
-			mostRecentCommit = commit
+		tagName := tag.Name().Short()
+		if versionRegex.MatchString(tagName) {
+			tagList = append(tagList, ParseSemanticVersion(tagName))
 		}
-
 		return nil
 	})
 
@@ -151,7 +139,11 @@ func getLatestTagCommit(r *git.Repository) (*object.Commit, error) {
 		return nil, fmt.Errorf("failed to iterate over tags: %v", err)
 	}
 
-	return mostRecentCommit, nil
+	sort.Slice(tagList, func(i, j int) bool {
+		return tagList[i].IsLessThan(tagList[j])
+	})
+
+	return tagList, nil
 }
 
 func getCommitTypeSinceTag(r *git.Repository, tagCommit *object.Commit) (CommitType, error) {
@@ -196,19 +188,14 @@ func getCommitTypeSinceTag(r *git.Repository, tagCommit *object.Commit) (CommitT
 }
 
 func containsBreakingChangeFooter(message string) bool {
-	// Split the commit message by newline to get the footer text
 	lines := strings.Split(message, "\n")
-
-	// Check last lines for the "BREAKING CHANGE" footer
 	for i := len(lines) - 1; i >= 0; i-- {
 		if strings.TrimSpace(lines[i]) == "" {
-			// Stop checking when an empty line (beginning of the commit body) is reached
 			break
 		}
 		if strings.Contains(strings.ToLower(lines[i]), "breaking change:") {
 			return true
 		}
 	}
-
 	return false
 }