diff --git a/source/dub/internal/git.d b/source/dub/internal/git.d
index d1e52d6..d7e169f 100644
--- a/source/dub/internal/git.d
+++ b/source/dub/internal/git.d
@@ -65,9 +65,6 @@
 // by invoking the "git" executable
 private string determineVersionWithGitTool(NativePath path)
 {
-	import dub.semver;
-	import std.algorithm : canFind;
-	import std.conv : to;
 	import std.process;
 
 	auto git_dir = path ~ ".git";
@@ -81,17 +78,9 @@
 		return null;
 	}
 
-	auto tag = exec("git", git_dir_param, "describe", "--long", "--tags");
-	if (tag !is null) {
-		auto parts = tag.split("-");
-		auto commit = parts[$-1];
-		auto num = parts[$-2].to!int;
-		tag = parts[0 .. $-2].join("-");
-		if (tag.startsWith("v") && isValidVersion(tag[1 .. $])) {
-			if (num == 0) return tag[1 .. $];
-			else if (tag.canFind("+")) return format("%s.commit.%s.%s", tag[1 .. $], num, commit);
-			else return format("%s+commit.%s.%s", tag[1 .. $], num, commit);
-		}
+	if (const describeOutput = exec("git", git_dir_param, "describe", "--long", "--tags")) {
+		if (const ver = determineVersionFromGitDescribe(describeOutput))
+			return ver;
 	}
 
 	auto branch = exec("git", git_dir_param, "rev-parse", "--abbrev-ref", "HEAD");
@@ -102,6 +91,49 @@
 	return null;
 }
 
+private string determineVersionFromGitDescribe(string describeOutput)
+{
+	import dub.semver : isValidVersion;
+	import std.conv : to;
+
+	const parts = describeOutput.split("-");
+	const commit = parts[$-1];
+	const num = parts[$-2].to!int;
+	const tag = parts[0 .. $-2].join("-");
+	if (tag.startsWith("v") && isValidVersion(tag[1 .. $])) {
+		if (num == 0) return tag[1 .. $];
+		const i = tag.indexOf('+');
+		auto r = format("%s%scommit.%s.%s", tag[1 .. (i < 0) ? $ : i],
+			parts.length > 3 ? "." : "-", num, commit);
+		if (i > 0) r ~= tag[i .. $];
+		return r;
+	}
+	return null;
+}
+
+unittest {
+	// tag v1.0.0
+	assert(determineVersionFromGitDescribe("v1.0.0-0-deadbeef") == "1.0.0");
+	// 1 commit after v1.0.0
+	assert(determineVersionFromGitDescribe("v1.0.0-1-deadbeef") == "1.0.0-commit.1.deadbeef");
+	// tag v1.0.0+2.0.0
+	assert(determineVersionFromGitDescribe("v1.0.0+2.0.0-0-deadbeef") == "1.0.0+2.0.0");
+	// 12 commits after tag v1.0.0+2.0.0
+	assert(determineVersionFromGitDescribe("v1.0.0+2.0.0-12-deadbeef") == "1.0.0-commit.12.deadbeef+2.0.0");
+	// tag v1.0.0-beta.1
+	assert(determineVersionFromGitDescribe("v1.0.0-beta.1-0-deadbeef") == "1.0.0-beta.1");
+	// 2 commits after tag v1.0.0-beta.1
+	assert(determineVersionFromGitDescribe("v1.0.0-beta.1-2-deadbeef") == "1.0.0-beta.1.commit.2.deadbeef");
+	// tag v1.0.0-beta.2+2.0.0
+	assert(determineVersionFromGitDescribe("v1.0.0-beta.2+2.0.0-0-deadbeef") == "1.0.0-beta.2+2.0.0");
+	// 3 commits after tag v1.0.0-beta.2+2.0.0
+	assert(determineVersionFromGitDescribe("v1.0.0-beta.2+2.0.0-3-deadbeef") == "1.0.0-beta.2.commit.3.deadbeef+2.0.0");
+
+	// invalid tags
+	assert(determineVersionFromGitDescribe("1.0.0-0-deadbeef") is null);
+	assert(determineVersionFromGitDescribe("v1.0-0-deadbeef") is null);
+}
+
 /** Clones a repository into a new directory.
 
 	Params: