diff --git a/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java b/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java
index 4a03801dbeb4d999a915b0af8b1b69a550bebdb4..0de27619547e923f5c4bc7a9624c874fac05cadf 100644
--- a/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java
+++ b/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java
@@ -22,9 +22,8 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.stream.Collectors;
 
-import org.apache.commons.io.FileUtils;
-
 import de.uni_passau.fim.seibt.gitwrapper.process.ProcessExecutor.ExecRes;
+import org.apache.commons.io.FileUtils;
 
 /**
  * A git {@link Repository}.
@@ -53,6 +52,10 @@ public class Repository {
     private static final String CONFLICT_MIDDLE = "=======";
     private static final String CONFLICT_END = ">>>>>>>";
 
+    // The prefixes of the full symbolic names of (remote) branches.
+    private static final String FULL_SYMBOLIC_BRANCH = "refs/heads/";
+    private static final String FULL_SYMBOLIC_REMOTE_BRANCH = "refs/remotes/";
+
     private GitWrapper git;
 
     private String url;
@@ -234,43 +237,11 @@ public class Repository {
             return Optional.of(commits.get(id));
         }
 
-        if (!isCommit(id)) {
-            return Optional.empty();
-        }
-
-        return toHash(id).map(sha1 -> commits.computeIfAbsent(sha1, fullID -> new Commit(this, fullID)));
+        return verify(false, id, TYPE_COMMIT).map(sha1 -> commits.computeIfAbsent(sha1, fullID -> new Commit(this, fullID)));
     }
 
     /**
-     * Determines whether the given object ID designates a commit.
-     *
-     * @param id
-     *         the ID to check
-     * @return true if the ID designates a commit
-     */
-    private boolean isCommit(String id) {
-        Optional<ExecRes> catFile = git.exec(dir, "cat-file", "-t", id);
-        Function<ExecRes, Boolean> toBoolean = res -> {
-
-            if (git.failed(res)) {
-                LOG.warning(() -> String.format("Failed to determine whether %s is a valid commit id.", id));
-                return null;
-            }
-
-            boolean isCommit = res.getStdOutTrimmed().startsWith(TYPE_COMMIT);
-
-            if (isCommit) {
-                LOG.finer(() -> String.format("%s is a commit.", id));
-            }
-
-            return isCommit;
-        };
-
-        return catFile.map(toBoolean).orElse(false);
-    }
-
-    /**
-     * Optionally returns a {@link Branch} for the given name. If the given name does not designated a branch that
+     * Optionally returns a {@link Branch} for the given name. If the given name does not designate a branch that
      * exists in this {@link Repository}, an empty {@link Optional} will be returned.
      *
      * @param name
@@ -282,39 +253,27 @@ public class Repository {
             return Optional.of(branches.get(name));
         }
 
-        if (!isBranch(name)) {
-            return Optional.empty();
-        }
-
-        return Optional.of(branches.computeIfAbsent(name, theName -> new Branch(this, theName)));
-    }
-
-    /**
-     * Determines whether the given name designates a branch.
-     *
-     * @param name
-     *         the branch name to check
-     * @return true if the ID designates a commit
-     */
-    private boolean isBranch(String name) {
-        Optional<ExecRes> catFile = git.exec(dir, "branch", "--list", "--no-color", "--column=plain");
-        Function<ExecRes, Boolean> toBoolean = res -> {
-
-            if (git.failed(res)) {
-                LOG.warning(() -> String.format("Failed to determine whether %s is a valid branch id.", name));
+        Function<String, Branch> toBranch = fullName -> {
+            if (fullName.isEmpty()) {
+                LOG.warning(() -> String.format("The name '%s' does not designate a branch in %s.", name, this));
                 return null;
             }
 
-            boolean isBranch = res.stdOut.contains(name);
+            String branchName;
 
-            if (isBranch) {
-                LOG.finer(() -> String.format("%s is a branch.", name));
+            if (fullName.startsWith(FULL_SYMBOLIC_BRANCH)) {
+                branchName = fullName.substring(FULL_SYMBOLIC_BRANCH.length());
+            } else if (fullName.startsWith(FULL_SYMBOLIC_REMOTE_BRANCH)) {
+                branchName = fullName.substring(FULL_SYMBOLIC_REMOTE_BRANCH.length());
+            } else {
+                LOG.warning(() -> String.format("The name '%s' designates neither a local nor a remote branch in %s.", fullName, this));
+                return null;
             }
 
-            return isBranch;
+            return branches.computeIfAbsent(branchName, newBranchName -> new Branch(this, newBranchName));
         };
 
-        return catFile.map(toBoolean).orElse(false);
+        return verify(true, name, null).map(toBranch);
     }
 
     /**
@@ -322,20 +281,50 @@ public class Repository {
      *
      * @param id
      *         the <code>id</code> to transform
-     * @return the full SHA1 hash or an empty {@link Optional} if an exception occurs
+     * @return the full SHA1 hash or an empty {@link Optional} if an exception occurs or {@code id} can not be converted
+     *         to its associated git hash
      */
     Optional<String> toHash(String id) {
-        Optional<ExecRes> revParse = git.exec(dir, "rev-parse", id);
+        return verify(false, id, null);
+    }
+
+    /**
+     * Verifies that the given git-thing exists and can be resolved to a raw SHA1 hash. If type is not {@link null},
+     * git will be asked to verify that the thing is also of the given type. If {@code fullSymbolicName} is set, the
+     * returned {@code String} will be (if present) the full symbolic name of the reference. If {@code arg} does
+     * not designate a reference but does exist in the repository, an empty {@code String} will be returned. This
+     * is the case (for example) for an existing commit in the repository.
+     *
+     * @param fullSymbolicName
+     *         whether to return the full symbolic name of {@code arg} if possible
+     * @param arg
+     *         the thing to check
+     * @param type
+     *         the type of the thing, ignored if {@code null}
+     * @return optionally the full SHA1 hash (or full symbolic name) or an empty {@link Optional} if the thing can not
+     *         be found or turned into a full hash
+     */
+    private Optional<String> verify(boolean fullSymbolicName, String arg, String type) {
+        String argument = type != null ? String.format("%s^{%s}", arg, type) : arg;
+        Optional<ExecRes> revParse;
+
+        if (fullSymbolicName) {
+            revParse = git.exec(dir, "rev-parse", "--symbolic-full-name", "--verify", argument);
+        } else {
+            revParse = git.exec(dir, "rev-parse", "--verify", argument);
+        }
+
         Function<ExecRes, String> toHash = res -> {
 
             if (git.failed(res)) {
-                LOG.warning(() -> String.format("Failed to resolve %s to its unique SHA1 hash.", id));
+                LOG.warning(() -> String.format("Failed to resolve '%s' to its unique SHA1 hash.", arg));
                 return null;
             }
 
-            LOG.finer(() -> String.format("Resolved %s to %s.", id, res.getStdOutTrimmed()));
+            String hash = res.getStdOutTrimmed();
+            LOG.finer(() -> String.format("Verified that %s exists and resolved it to %s.", arg, hash));
 
-            return res.getStdOutTrimmed();
+            return hash;
         };
 
         return revParse.map(toHash);