about summary refs log tree commit
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2018-04-10 08:25:45 +0900
committerJunio C Hamano <gitster@pobox.com>2018-04-10 08:25:45 +0900
commita5bbc29994b22ab0b57c4dc9568a261d32476e94 (patch)
tree4cf0247ad3bac3f8130f83a2f9b40197a24fab0f
parent78c20b8fcaf0c46942a8c91e38076358f9a948ac (diff)
parent1a750441a7360b29fff7a414649ece1d35acaca6 (diff)
downloadgit-a5bbc29994b22ab0b57c4dc9568a261d32476e94.tar.gz
Conversion from uchar[20] to struct object_id continues.

* bc/object-id: (36 commits)
  convert: convert to struct object_id
  sha1_file: introduce a constant for max header length
  Convert lookup_replace_object to struct object_id
  sha1_file: convert read_sha1_file to struct object_id
  sha1_file: convert read_object_with_reference to object_id
  tree-walk: convert tree entry functions to object_id
  streaming: convert istream internals to struct object_id
  tree-walk: convert get_tree_entry_follow_symlinks internals to object_id
  builtin/notes: convert static functions to object_id
  builtin/fmt-merge-msg: convert remaining code to object_id
  sha1_file: convert sha1_object_info* to object_id
  Convert remaining callers of sha1_object_info_extended to object_id
  packfile: convert unpack_entry to struct object_id
  sha1_file: convert retry_bad_packed_offset to struct object_id
  sha1_file: convert assert_sha1_type to object_id
  builtin/mktree: convert to struct object_id
  streaming: convert open_istream to use struct object_id
  sha1_file: convert check_sha1_signature to struct object_id
  sha1_file: convert read_loose_object to use struct object_id
  builtin/index-pack: convert struct ref_delta_entry to object_id
  ...
-rw-r--r--apply.c4
-rw-r--r--archive-tar.c28
-rw-r--r--archive-zip.c18
-rw-r--r--archive.c32
-rw-r--r--archive.h10
-rw-r--r--bisect.c3
-rw-r--r--blame.c18
-rw-r--r--builtin/am.c8
-rw-r--r--builtin/blame.c4
-rw-r--r--builtin/branch.c2
-rw-r--r--builtin/cat-file.c30
-rw-r--r--builtin/checkout.c12
-rw-r--r--builtin/commit-tree.c2
-rw-r--r--builtin/describe.c6
-rw-r--r--builtin/difftool.c2
-rw-r--r--builtin/fast-export.c8
-rw-r--r--builtin/fetch.c10
-rw-r--r--builtin/fmt-merge-msg.c4
-rw-r--r--builtin/fsck.c4
-rw-r--r--builtin/grep.c6
-rw-r--r--builtin/index-pack.c43
-rw-r--r--builtin/log.c8
-rw-r--r--builtin/ls-files.c4
-rw-r--r--builtin/ls-tree.c8
-rw-r--r--builtin/merge-tree.c5
-rw-r--r--builtin/merge.c8
-rw-r--r--builtin/mktag.c20
-rw-r--r--builtin/mktree.c24
-rw-r--r--builtin/name-rev.c2
-rw-r--r--builtin/notes.c14
-rw-r--r--builtin/pack-objects.c27
-rw-r--r--builtin/prune.c2
-rw-r--r--builtin/receive-pack.c8
-rw-r--r--builtin/reflog.c2
-rw-r--r--builtin/replace.c10
-rw-r--r--builtin/reset.c2
-rw-r--r--builtin/rev-list.c2
-rw-r--r--builtin/rev-parse.c2
-rw-r--r--builtin/rm.c2
-rw-r--r--builtin/show-branch.c2
-rw-r--r--builtin/show-ref.c4
-rw-r--r--builtin/tag.c16
-rw-r--r--builtin/unpack-file.c2
-rw-r--r--builtin/unpack-objects.c4
-rw-r--r--builtin/update-index.c2
-rw-r--r--builtin/verify-commit.c2
-rw-r--r--builtin/worktree.c4
-rw-r--r--builtin/write-tree.c6
-rw-r--r--bulk-checkin.c18
-rw-r--r--bulk-checkin.h2
-rw-r--r--bundle.c2
-rw-r--r--cache-tree.c39
-rw-r--r--cache-tree.h4
-rw-r--r--cache.h42
-rw-r--r--combine-diff.c6
-rw-r--r--commit.c8
-rw-r--r--config.c2
-rw-r--r--convert.c12
-rw-r--r--convert.h2
-rw-r--r--diff.c6
-rw-r--r--dir.c2
-rw-r--r--entry.c4
-rw-r--r--fast-import.c31
-rw-r--r--fsck.c2
-rw-r--r--grep.c2
-rw-r--r--http-push.c2
-rw-r--r--http-walker.c16
-rw-r--r--line-log.c3
-rw-r--r--list-objects-filter.c2
-rw-r--r--log-tree.c12
-rw-r--r--mailmap.c2
-rw-r--r--match-trees.c10
-rw-r--r--merge-blobs.c4
-rw-r--r--merge-recursive.c38
-rw-r--r--notes-cache.c2
-rw-r--r--notes-merge.c2
-rw-r--r--notes.c10
-rw-r--r--object.c12
-rw-r--r--pack-bitmap-write.c3
-rw-r--r--pack-check.c4
-rw-r--r--packfile.c30
-rw-r--r--pretty.c8
-rw-r--r--reachable.c2
-rw-r--r--read-cache.c4
-rw-r--r--ref-filter.c14
-rw-r--r--refs.c2
-rw-r--r--remote-testsvn.c4
-rw-r--r--remote.c2
-rw-r--r--replace_object.c26
-rw-r--r--rerere.c4
-rw-r--r--resolve-undo.c15
-rw-r--r--resolve-undo.h2
-rw-r--r--send-pack.c12
-rw-r--r--sequencer.c9
-rw-r--r--sha1_file.c137
-rw-r--r--sha1_name.c31
-rw-r--r--strbuf.c4
-rw-r--r--strbuf.h8
-rw-r--r--streaming.c18
-rw-r--r--streaming.h2
-rw-r--r--submodule-config.c2
-rw-r--r--submodule.c6
-rw-r--r--tag.c10
-rw-r--r--transport.c6
-rw-r--r--tree-walk.c45
-rw-r--r--tree-walk.h2
-rw-r--r--tree.c16
-rw-r--r--tree.h2
-rw-r--r--wt-status.c20
-rw-r--r--wt-status.h6
-rw-r--r--xdiff-interface.c2
111 files changed, 609 insertions, 594 deletions
diff --git a/apply.c b/apply.c
index 134dc7ba78..7e5792c996 100644
--- a/apply.c
+++ b/apply.c
@@ -3180,7 +3180,7 @@ static int apply_binary(struct apply_state *state,
                 unsigned long size;
                 char *result;
 
-                result = read_sha1_file(oid.hash, &type, &size);
+                result = read_object_file(&oid, &type, &size);
                 if (!result)
                         return error(_("the necessary postimage %s for "
                                        "'%s' cannot be read"),
@@ -3242,7 +3242,7 @@ static int read_blob_object(struct strbuf *buf, const struct object_id *oid, uns
                 unsigned long sz;
                 char *result;
 
-                result = read_sha1_file(oid->hash, &type, &sz);
+                result = read_object_file(oid, &type, &sz);
                 if (!result)
                         return -1;
                 /* XXX read_sha1_file NUL-terminates */
diff --git a/archive-tar.c b/archive-tar.c
index c6ed96ee74..3563bcb9f2 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -111,7 +111,7 @@ static void write_trailer(void)
  * queues up writes, so that all our write(2) calls write exactly one
  * full block; pads writes to RECORDSIZE
  */
-static int stream_blocked(const unsigned char *sha1)
+static int stream_blocked(const struct object_id *oid)
 {
         struct git_istream *st;
         enum object_type type;
@@ -119,9 +119,9 @@ static int stream_blocked(const unsigned char *sha1)
         char buf[BLOCKSIZE];
         ssize_t readlen;
 
-        st = open_istream(sha1, &type, &sz, NULL);
+        st = open_istream(oid, &type, &sz, NULL);
         if (!st)
-                return error("cannot stream blob %s", sha1_to_hex(sha1));
+                return error("cannot stream blob %s", oid_to_hex(oid));
         for (;;) {
                 readlen = read_istream(st, buf, sizeof(buf));
                 if (readlen <= 0)
@@ -218,7 +218,7 @@ static void prepare_header(struct archiver_args *args,
 }
 
 static void write_extended_header(struct archiver_args *args,
-                                  const unsigned char *sha1,
+                                  const struct object_id *oid,
                                   const void *buffer, unsigned long size)
 {
         struct ustar_header header;
@@ -226,14 +226,14 @@ static void write_extended_header(struct archiver_args *args,
         memset(&header, 0, sizeof(header));
         *header.typeflag = TYPEFLAG_EXT_HEADER;
         mode = 0100666;
-        xsnprintf(header.name, sizeof(header.name), "%s.paxheader", sha1_to_hex(sha1));
+        xsnprintf(header.name, sizeof(header.name), "%s.paxheader", oid_to_hex(oid));
         prepare_header(args, &header, mode, size);
         write_blocked(&header, sizeof(header));
         write_blocked(buffer, size);
 }
 
 static int write_tar_entry(struct archiver_args *args,
-                           const unsigned char *sha1,
+                           const struct object_id *oid,
                            const char *path, size_t pathlen,
                            unsigned int mode)
 {
@@ -257,7 +257,7 @@ static int write_tar_entry(struct archiver_args *args,
                 mode = (mode | ((mode & 0100) ? 0777 : 0666)) & ~tar_umask;
         } else {
                 return error("unsupported file mode: 0%o (SHA1: %s)",
-                             mode, sha1_to_hex(sha1));
+                             mode, oid_to_hex(oid));
         }
         if (pathlen > sizeof(header.name)) {
                 size_t plen = get_path_prefix(path, pathlen,
@@ -268,7 +268,7 @@ static int write_tar_entry(struct archiver_args *args,
                         memcpy(header.name, path + plen + 1, rest);
                 } else {
                         xsnprintf(header.name, sizeof(header.name), "%s.data",
-                                  sha1_to_hex(sha1));
+                                  oid_to_hex(oid));
                         strbuf_append_ext_header(&ext_header, "path",
                                                  path, pathlen);
                 }
@@ -276,14 +276,14 @@ static int write_tar_entry(struct archiver_args *args,
                 memcpy(header.name, path, pathlen);
 
         if (S_ISREG(mode) && !args->convert &&
-            sha1_object_info(sha1, &size) == OBJ_BLOB &&
+            oid_object_info(oid, &size) == OBJ_BLOB &&
             size > big_file_threshold)
                 buffer = NULL;
         else if (S_ISLNK(mode) || S_ISREG(mode)) {
                 enum object_type type;
-                buffer = sha1_file_to_archive(args, path, sha1, old_mode, &type, &size);
+                buffer = object_file_to_archive(args, path, oid, old_mode, &type, &size);
                 if (!buffer)
-                        return error("cannot read %s", sha1_to_hex(sha1));
+                        return error("cannot read %s", oid_to_hex(oid));
         } else {
                 buffer = NULL;
                 size = 0;
@@ -292,7 +292,7 @@ static int write_tar_entry(struct archiver_args *args,
         if (S_ISLNK(mode)) {
                 if (size > sizeof(header.linkname)) {
                         xsnprintf(header.linkname, sizeof(header.linkname),
-                                  "see %s.paxheader", sha1_to_hex(sha1));
+                                  "see %s.paxheader", oid_to_hex(oid));
                         strbuf_append_ext_header(&ext_header, "linkpath",
                                                  buffer, size);
                 } else
@@ -308,7 +308,7 @@ static int write_tar_entry(struct archiver_args *args,
         prepare_header(args, &header, mode, size_in_header);
 
         if (ext_header.len > 0) {
-                write_extended_header(args, sha1, ext_header.buf,
+                write_extended_header(args, oid, ext_header.buf,
                                       ext_header.len);
         }
         strbuf_release(&ext_header);
@@ -317,7 +317,7 @@ static int write_tar_entry(struct archiver_args *args,
                 if (buffer)
                         write_blocked(buffer, size);
                 else
-                        err = stream_blocked(sha1);
+                        err = stream_blocked(oid);
         }
         free(buffer);
         return err;
diff --git a/archive-zip.c b/archive-zip.c
index e8913e5a26..6b20bce4d1 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -276,7 +276,7 @@ static int entry_is_binary(const char *path, const void *buffer, size_t size)
 #define STREAM_BUFFER_SIZE (1024 * 16)
 
 static int write_zip_entry(struct archiver_args *args,
-                           const unsigned char *sha1,
+                           const struct object_id *oid,
                            const char *path, size_t pathlen,
                            unsigned int mode)
 {
@@ -314,7 +314,7 @@ static int write_zip_entry(struct archiver_args *args,
 
         if (pathlen > 0xffff) {
                 return error("path too long (%d chars, SHA1: %s): %s",
-                                (int)pathlen, sha1_to_hex(sha1), path);
+                                (int)pathlen, oid_to_hex(oid), path);
         }
 
         if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
@@ -325,7 +325,7 @@ static int write_zip_entry(struct archiver_args *args,
                 compressed_size = 0;
                 buffer = NULL;
         } else if (S_ISREG(mode) || S_ISLNK(mode)) {
-                enum object_type type = sha1_object_info(sha1, &size);
+                enum object_type type = oid_object_info(oid, &size);
 
                 method = 0;
                 attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) :
@@ -337,18 +337,18 @@ static int write_zip_entry(struct archiver_args *args,
 
                 if (S_ISREG(mode) && type == OBJ_BLOB && !args->convert &&
                     size > big_file_threshold) {
-                        stream = open_istream(sha1, &type, &size, NULL);
+                        stream = open_istream(oid, &type, &size, NULL);
                         if (!stream)
                                 return error("cannot stream blob %s",
-                                             sha1_to_hex(sha1));
+                                             oid_to_hex(oid));
                         flags |= ZIP_STREAM;
                         out = buffer = NULL;
                 } else {
-                        buffer = sha1_file_to_archive(args, path, sha1, mode,
-                                                      &type, &size);
+                        buffer = object_file_to_archive(args, path, oid, mode,
+                                                        &type, &size);
                         if (!buffer)
                                 return error("cannot read %s",
-                                             sha1_to_hex(sha1));
+                                             oid_to_hex(oid));
                         crc = crc32(crc, buffer, size);
                         is_binary = entry_is_binary(path_without_prefix,
                                                     buffer, size);
@@ -357,7 +357,7 @@ static int write_zip_entry(struct archiver_args *args,
                 compressed_size = (method == 0) ? size : 0;
         } else {
                 return error("unsupported file mode: 0%o (SHA1: %s)", mode,
-                                sha1_to_hex(sha1));
+                                oid_to_hex(oid));
         }
 
         if (creator_version > max_creator_version)
diff --git a/archive.c b/archive.c
index 0b7b62af0c..93ab175b0b 100644
--- a/archive.c
+++ b/archive.c
@@ -63,16 +63,16 @@ static void format_subst(const struct commit *commit,
         free(to_free);
 }
 
-void *sha1_file_to_archive(const struct archiver_args *args,
-                           const char *path, const unsigned char *sha1,
-                           unsigned int mode, enum object_type *type,
-                           unsigned long *sizep)
+void *object_file_to_archive(const struct archiver_args *args,
+                             const char *path, const struct object_id *oid,
+                             unsigned int mode, enum object_type *type,
+                             unsigned long *sizep)
 {
         void *buffer;
         const struct commit *commit = args->convert ? args->commit : NULL;
 
         path += args->baselen;
-        buffer = read_sha1_file(sha1, type, sizep);
+        buffer = read_object_file(oid, type, sizep);
         if (buffer && S_ISREG(mode)) {
                 struct strbuf buf = STRBUF_INIT;
                 size_t size = 0;
@@ -121,7 +121,7 @@ static int check_attr_export_subst(const struct attr_check *check)
         return check && ATTR_TRUE(check->items[1].value);
 }
 
-static int write_archive_entry(const unsigned char *sha1, const char *base,
+static int write_archive_entry(const struct object_id *oid, const char *base,
                 int baselen, const char *filename, unsigned mode, int stage,
                 void *context)
 {
@@ -153,7 +153,7 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
         if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
                 if (args->verbose)
                         fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
-                err = write_entry(args, sha1, path.buf, path.len, mode);
+                err = write_entry(args, oid, path.buf, path.len, mode);
                 if (err)
                         return err;
                 return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
@@ -161,7 +161,7 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
 
         if (args->verbose)
                 fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
-        return write_entry(args, sha1, path.buf, path.len, mode);
+        return write_entry(args, oid, path.buf, path.len, mode);
 }
 
 static void queue_directory(const unsigned char *sha1,
@@ -191,14 +191,14 @@ static int write_directory(struct archiver_context *c)
         d->path[d->len - 1] = '\0'; /* no trailing slash */
         ret =
                 write_directory(c) ||
-                write_archive_entry(d->oid.hash, d->path, d->baselen,
+                write_archive_entry(&d->oid, d->path, d->baselen,
                                     d->path + d->baselen, d->mode,
                                     d->stage, c) != READ_TREE_RECURSIVE;
         free(d);
         return ret ? -1 : 0;
 }
 
-static int queue_or_write_archive_entry(const unsigned char *sha1,
+static int queue_or_write_archive_entry(const struct object_id *oid,
                 struct strbuf *base, const char *filename,
                 unsigned mode, int stage, void *context)
 {
@@ -224,14 +224,14 @@ static int queue_or_write_archive_entry(const unsigned char *sha1,
 
                 if (check_attr_export_ignore(check))
                         return 0;
-                queue_directory(sha1, base, filename,
+                queue_directory(oid->hash, base, filename,
                                 mode, stage, c);
                 return READ_TREE_RECURSIVE;
         }
 
         if (write_directory(c))
                 return -1;
-        return write_archive_entry(sha1, base->buf, base->len, filename, mode,
+        return write_archive_entry(oid, base->buf, base->len, filename, mode,
                                    stage, context);
 }
 
@@ -250,7 +250,7 @@ int write_archive_entries(struct archiver_args *args,
                         len--;
                 if (args->verbose)
                         fprintf(stderr, "%.*s\n", (int)len, args->base);
-                err = write_entry(args, args->tree->object.oid.hash, args->base,
+                err = write_entry(args, &args->tree->object.oid, args->base,
                                   len, 040777);
                 if (err)
                         return err;
@@ -303,7 +303,7 @@ static const struct archiver *lookup_archiver(const char *name)
         return NULL;
 }
 
-static int reject_entry(const unsigned char *sha1, struct strbuf *base,
+static int reject_entry(const struct object_id *oid, struct strbuf *base,
                         const char *filename, unsigned mode,
                         int stage, void *context)
 {
@@ -397,8 +397,8 @@ static void parse_treeish_arg(const char **argv,
                 unsigned int mode;
                 int err;
 
-                err = get_tree_entry(tree->object.oid.hash, prefix,
-                                     tree_oid.hash, &mode);
+                err = get_tree_entry(&tree->object.oid, prefix, &tree_oid,
+                                     &mode);
                 if (err || !S_ISDIR(mode))
                         die("current working directory is untracked");
 
diff --git a/archive.h b/archive.h
index 62d1d82c1a..1f9954f7cd 100644
--- a/archive.h
+++ b/archive.h
@@ -31,7 +31,7 @@ extern void init_tar_archiver(void);
 extern void init_zip_archiver(void);
 
 typedef int (*write_archive_entry_fn_t)(struct archiver_args *args,
-                                        const unsigned char *sha1,
+                                        const struct object_id *oid,
                                         const char *path, size_t pathlen,
                                         unsigned int mode);
 
@@ -39,9 +39,9 @@ extern int write_archive_entries(struct archiver_args *args, write_archive_entry
 extern int write_archive(int argc, const char **argv, const char *prefix, const char *name_hint, int remote);
 
 const char *archive_format_from_filename(const char *filename);
-extern void *sha1_file_to_archive(const struct archiver_args *args,
-                                  const char *path, const unsigned char *sha1,
-                                  unsigned int mode, enum object_type *type,
-                                  unsigned long *sizep);
+extern void *object_file_to_archive(const struct archiver_args *args,
+                                    const char *path, const struct object_id *oid,
+                                    unsigned int mode, enum object_type *type,
+                                    unsigned long *sizep);
 
 #endif        /* ARCHIVE_H */
diff --git a/bisect.c b/bisect.c
index f6d05bd66f..ad395bb2b8 100644
--- a/bisect.c
+++ b/bisect.c
@@ -132,7 +132,8 @@ static void show_list(const char *debug, int counted, int nr,
                 unsigned flags = commit->object.flags;
                 enum object_type type;
                 unsigned long size;
-                char *buf = read_sha1_file(commit->object.oid.hash, &type, &size);
+                char *buf = read_object_file(&commit->object.oid, &type,
+                                             &size);
                 const char *subject_start;
                 int subject_len;
 
diff --git a/blame.c b/blame.c
index 200e0ad9a2..78c9808bd1 100644
--- a/blame.c
+++ b/blame.c
@@ -80,8 +80,8 @@ static void verify_working_tree_path(struct commit *work_tree, const char *path)
                 struct object_id blob_oid;
                 unsigned mode;
 
-                if (!get_tree_entry(commit_oid->hash, path, blob_oid.hash, &mode) &&
-                    sha1_object_info(blob_oid.hash, NULL) == OBJ_BLOB)
+                if (!get_tree_entry(commit_oid, path, &blob_oid, &mode) &&
+                    oid_object_info(&blob_oid, NULL) == OBJ_BLOB)
                         return;
         }
 
@@ -297,8 +297,8 @@ static void fill_origin_blob(struct diff_options *opt,
                     textconv_object(o->path, o->mode, &o->blob_oid, 1, &file->ptr, &file_size))
                         ;
                 else
-                        file->ptr = read_sha1_file(o->blob_oid.hash, &type,
-                                                   &file_size);
+                        file->ptr = read_object_file(&o->blob_oid, &type,
+                                                     &file_size);
                 file->size = file_size;
 
                 if (!file->ptr)
@@ -502,11 +502,9 @@ static int fill_blob_sha1_and_mode(struct blame_origin *origin)
 {
         if (!is_null_oid(&origin->blob_oid))
                 return 0;
-        if (get_tree_entry(origin->commit->object.oid.hash,
-                           origin->path,
-                           origin->blob_oid.hash, &origin->mode))
+        if (get_tree_entry(&origin->commit->object.oid, origin->path, &origin->blob_oid, &origin->mode))
                 goto error_out;
-        if (sha1_object_info(origin->blob_oid.hash, NULL) != OBJ_BLOB)
+        if (oid_object_info(&origin->blob_oid, NULL) != OBJ_BLOB)
                 goto error_out;
         return 0;
  error_out:
@@ -1831,8 +1829,8 @@ void setup_scoreboard(struct blame_scoreboard *sb, const char *path, struct blam
                                     &sb->final_buf_size))
                         ;
                 else
-                        sb->final_buf = read_sha1_file(o->blob_oid.hash, &type,
-                                                       &sb->final_buf_size);
+                        sb->final_buf = read_object_file(&o->blob_oid, &type,
+                                                         &sb->final_buf_size);
 
                 if (!sb->final_buf)
                         die(_("cannot read blob %s for path %s"),
diff --git a/builtin/am.c b/builtin/am.c
index 1151b5c73a..1bcc3606c5 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1550,7 +1550,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
         discard_cache();
         read_cache_from(index_path);
 
-        if (write_index_as_tree(orig_tree.hash, &the_index, index_path, 0, NULL))
+        if (write_index_as_tree(&orig_tree, &the_index, index_path, 0, NULL))
                 return error(_("Repository lacks necessary blobs to fall back on 3-way merge."));
 
         say(state, stdout, _("Using index info to reconstruct a base tree..."));
@@ -1575,7 +1575,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
                 return error(_("Did you hand edit your patch?\n"
                                 "It does not apply to blobs recorded in its index."));
 
-        if (write_index_as_tree(their_tree.hash, &the_index, index_path, 0, NULL))
+        if (write_index_as_tree(&their_tree, &the_index, index_path, 0, NULL))
                 return error("could not write tree");
 
         say(state, stdout, _("Falling back to patching base and 3-way merge..."));
@@ -1626,7 +1626,7 @@ static void do_commit(const struct am_state *state)
         if (run_hook_le(NULL, "pre-applypatch", NULL))
                 exit(1);
 
-        if (write_cache_as_tree(tree.hash, 0, NULL))
+        if (write_cache_as_tree(&tree, 0, NULL))
                 die(_("git write-tree failed to write a tree"));
 
         if (!get_oid_commit("HEAD", &parent)) {
@@ -2004,7 +2004,7 @@ static int clean_index(const struct object_id *head, const struct object_id *rem
         if (fast_forward_to(head_tree, head_tree, 1))
                 return -1;
 
-        if (write_cache_as_tree(index.hash, 0, NULL))
+        if (write_cache_as_tree(&index, 0, NULL))
                 return -1;
 
         index_tree = parse_tree_indirect(&index);
diff --git a/builtin/blame.c b/builtin/blame.c
index 9dcb367b90..f1a2fd6702 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -499,7 +499,7 @@ static int read_ancestry(const char *graft_file)
 
 static int update_auto_abbrev(int auto_abbrev, struct blame_origin *suspect)
 {
-        const char *uniq = find_unique_abbrev(suspect->commit->object.oid.hash,
+        const char *uniq = find_unique_abbrev(&suspect->commit->object.oid,
                                               auto_abbrev);
         int len = strlen(uniq);
         if (auto_abbrev < len)
@@ -655,7 +655,7 @@ static int is_a_rev(const char *name)
 
         if (get_oid(name, &oid))
                 return 0;
-        return OBJ_NONE < sha1_object_info(oid.hash, NULL);
+        return OBJ_NONE < oid_object_info(&oid, NULL);
 }
 
 int cmd_blame(int argc, const char **argv, const char *prefix)
diff --git a/builtin/branch.c b/builtin/branch.c
index 6d0cea9d4b..5bd2a0dd48 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -273,7 +273,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
                                bname.buf,
                                (flags & REF_ISBROKEN) ? "broken"
                                : (flags & REF_ISSYMREF) ? target
-                               : find_unique_abbrev(oid.hash, DEFAULT_ABBREV));
+                               : find_unique_abbrev(&oid, DEFAULT_ABBREV));
                 }
                 delete_branch_config(bname.buf);
 
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index d90170f070..2c46d257cd 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -32,7 +32,7 @@ static int filter_object(const char *path, unsigned mode,
 {
         enum object_type type;
 
-        *buf = read_sha1_file(oid->hash, &type, size);
+        *buf = read_object_file(oid, &type, size);
         if (!*buf)
                 return error(_("cannot read object %s '%s'"),
                              oid_to_hex(oid), path);
@@ -77,7 +77,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
         switch (opt) {
         case 't':
                 oi.type_name = &sb;
-                if (sha1_object_info_extended(oid.hash, &oi, flags) < 0)
+                if (oid_object_info_extended(&oid, &oi, flags) < 0)
                         die("git cat-file: could not get object info");
                 if (sb.len) {
                         printf("%s\n", sb.buf);
@@ -88,7 +88,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 
         case 's':
                 oi.sizep = &size;
-                if (sha1_object_info_extended(oid.hash, &oi, flags) < 0)
+                if (oid_object_info_extended(&oid, &oi, flags) < 0)
                         die("git cat-file: could not get object info");
                 printf("%lu\n", size);
                 return 0;
@@ -116,7 +116,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
                 /* else fallthrough */
 
         case 'p':
-                type = sha1_object_info(oid.hash, NULL);
+                type = oid_object_info(&oid, NULL);
                 if (type < 0)
                         die("Not a valid object name %s", obj_name);
 
@@ -130,7 +130,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 
                 if (type == OBJ_BLOB)
                         return stream_blob_to_fd(1, &oid, NULL, 0);
-                buf = read_sha1_file(oid.hash, &type, &size);
+                buf = read_object_file(&oid, &type, &size);
                 if (!buf)
                         die("Cannot read object %s", obj_name);
 
@@ -140,8 +140,9 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
         case 0:
                 if (type_from_string(exp_type) == OBJ_BLOB) {
                         struct object_id blob_oid;
-                        if (sha1_object_info(oid.hash, NULL) == OBJ_TAG) {
-                                char *buffer = read_sha1_file(oid.hash, &type, &size);
+                        if (oid_object_info(&oid, NULL) == OBJ_TAG) {
+                                char *buffer = read_object_file(&oid, &type,
+                                                                &size);
                                 const char *target;
                                 if (!skip_prefix(buffer, "object ", &target) ||
                                     get_oid_hex(target, &blob_oid))
@@ -150,7 +151,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
                         } else
                                 oidcpy(&blob_oid, &oid);
 
-                        if (sha1_object_info(blob_oid.hash, NULL) == OBJ_BLOB)
+                        if (oid_object_info(&blob_oid, NULL) == OBJ_BLOB)
                                 return stream_blob_to_fd(1, &blob_oid, NULL, 0);
                         /*
                          * we attempted to dereference a tag to a blob
@@ -159,7 +160,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
                          * fall-back to the usual case.
                          */
                 }
-                buf = read_object_with_reference(oid.hash, exp_type, &size, NULL);
+                buf = read_object_with_reference(&oid, exp_type, &size, NULL);
                 break;
 
         default:
@@ -304,8 +305,9 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d
                                 enum object_type type;
                                 if (!textconv_object(data->rest, 0100644, oid,
                                                      1, &contents, &size))
-                                        contents = read_sha1_file(oid->hash, &type,
-                                                                  &size);
+                                        contents = read_object_file(oid,
+                                                                    &type,
+                                                                    &size);
                                 if (!contents)
                                         die("could not convert '%s' %s",
                                             oid_to_hex(oid), data->rest);
@@ -321,7 +323,7 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d
                 unsigned long size;
                 void *contents;
 
-                contents = read_sha1_file(oid->hash, &type, &size);
+                contents = read_object_file(oid, &type, &size);
                 if (!contents)
                         die("object %s disappeared", oid_to_hex(oid));
                 if (type != data->type)
@@ -340,8 +342,8 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt,
         struct strbuf buf = STRBUF_INIT;
 
         if (!data->skip_object_info &&
-            sha1_object_info_extended(data->oid.hash, &data->info,
-                                      OBJECT_INFO_LOOKUP_REPLACE) < 0) {
+            oid_object_info_extended(&data->oid, &data->info,
+                                     OBJECT_INFO_LOOKUP_REPLACE) < 0) {
                 printf("%s missing\n",
                        obj_name ? obj_name : oid_to_hex(&data->oid));
                 fflush(stdout);
diff --git a/builtin/checkout.c b/builtin/checkout.c
index d76e13c852..b49b582071 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -66,7 +66,7 @@ static int post_checkout_hook(struct commit *old_commit, struct commit *new_comm
 
 }
 
-static int update_some(const unsigned char *sha1, struct strbuf *base,
+static int update_some(const struct object_id *oid, struct strbuf *base,
                 const char *pathname, unsigned mode, int stage, void *context)
 {
         int len;
@@ -78,7 +78,7 @@ static int update_some(const unsigned char *sha1, struct strbuf *base,
 
         len = base->len + strlen(pathname);
         ce = xcalloc(1, cache_entry_size(len));
-        hashcpy(ce->oid.hash, sha1);
+        oidcpy(&ce->oid, oid);
         memcpy(ce->name, base->buf, base->len);
         memcpy(ce->name + base->len, pathname, len - base->len);
         ce->ce_flags = create_ce_flags(0) | CE_UPDATE;
@@ -405,10 +405,10 @@ static void describe_detached_head(const char *msg, struct commit *commit)
                 pp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);
         if (print_sha1_ellipsis()) {
                 fprintf(stderr, "%s %s... %s\n", msg,
-                        find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV), sb.buf);
+                        find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV), sb.buf);
         } else {
                 fprintf(stderr, "%s %s %s\n", msg,
-                        find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV), sb.buf);
+                        find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV), sb.buf);
         }
         strbuf_release(&sb);
 }
@@ -720,7 +720,7 @@ static int add_pending_uninteresting_ref(const char *refname,
 static void describe_one_orphan(struct strbuf *sb, struct commit *commit)
 {
         strbuf_addstr(sb, "  ");
-        strbuf_add_unique_abbrev(sb, commit->object.oid.hash, DEFAULT_ABBREV);
+        strbuf_add_unique_abbrev(sb, &commit->object.oid, DEFAULT_ABBREV);
         strbuf_addch(sb, ' ');
         if (!parse_commit(commit))
                 pp_commit_easy(CMIT_FMT_ONELINE, commit, sb);
@@ -778,7 +778,7 @@ static void suggest_reattach(struct commit *commit, struct rev_info *revs)
                         " git branch <new-branch-name> %s\n\n",
                         /* Give ngettext() the count */
                         lost),
-                        find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));
+                        find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV));
 }
 
 /*
diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c
index e5bdf57b1e..ecf42191da 100644
--- a/builtin/commit-tree.c
+++ b/builtin/commit-tree.c
@@ -58,7 +58,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
                                 usage(commit_tree_usage);
                         if (get_oid_commit(argv[i], &oid))
                                 die("Not a valid object name %s", argv[i]);
-                        assert_sha1_type(oid.hash, OBJ_COMMIT);
+                        assert_oid_type(&oid, OBJ_COMMIT);
                         new_parent(lookup_commit(&oid), &parents);
                         continue;
                 }
diff --git a/builtin/describe.c b/builtin/describe.c
index e4869df7b4..de840f96a4 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -285,7 +285,7 @@ static void append_name(struct commit_name *n, struct strbuf *dst)
 
 static void append_suffix(int depth, const struct object_id *oid, struct strbuf *dst)
 {
-        strbuf_addf(dst, "-%d-g%s", depth, find_unique_abbrev(oid->hash, abbrev));
+        strbuf_addf(dst, "-%d-g%s", depth, find_unique_abbrev(oid, abbrev));
 }
 
 static void describe_commit(struct object_id *oid, struct strbuf *dst)
@@ -383,7 +383,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
         if (!match_cnt) {
                 struct object_id *cmit_oid = &cmit->object.oid;
                 if (always) {
-                        strbuf_add_unique_abbrev(dst, cmit_oid->hash, abbrev);
+                        strbuf_add_unique_abbrev(dst, cmit_oid, abbrev);
                         if (suffix)
                                 strbuf_addstr(dst, suffix);
                         return;
@@ -502,7 +502,7 @@ static void describe(const char *arg, int last_one)
 
         if (cmit)
                 describe_commit(&oid, &sb);
-        else if (sha1_object_info(oid.hash, NULL) == OBJ_BLOB)
+        else if (oid_object_info(&oid, NULL) == OBJ_BLOB)
                 describe_blob(oid, &sb);
         else
                 die(_("%s is neither a commit nor blob"), arg);
diff --git a/builtin/difftool.c b/builtin/difftool.c
index bcc79d1888..ee8dce019e 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -306,7 +306,7 @@ static char *get_symlink(const struct object_id *oid, const char *path)
         } else {
                 enum object_type type;
                 unsigned long size;
-                data = read_sha1_file(oid->hash, &type, &size);
+                data = read_object_file(oid, &type, &size);
                 if (!data)
                         die(_("could not read object %s for symlink %s"),
                                 oid_to_hex(oid), path);
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 27b2cc138e..a15898d641 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -237,10 +237,10 @@ static void export_blob(const struct object_id *oid)
                 object = (struct object *)lookup_blob(oid);
                 eaten = 0;
         } else {
-                buf = read_sha1_file(oid->hash, &type, &size);
+                buf = read_object_file(oid, &type, &size);
                 if (!buf)
                         die ("Could not read blob %s", oid_to_hex(oid));
-                if (check_sha1_signature(oid->hash, buf, size, type_name(type)) < 0)
+                if (check_object_signature(oid, buf, size, type_name(type)) < 0)
                         die("sha1 mismatch in blob %s", oid_to_hex(oid));
                 object = parse_object_buffer(oid, type, size, buf, &eaten);
         }
@@ -682,7 +682,7 @@ static void handle_tag(const char *name, struct tag *tag)
                 return;
         }
 
-        buf = read_sha1_file(tag->object.oid.hash, &type, &size);
+        buf = read_object_file(&tag->object.oid, &type, &size);
         if (!buf)
                 die ("Could not read tag %s", oid_to_hex(&tag->object.oid));
         message = memmem(buf, size, "\n\n", 2);
@@ -947,7 +947,7 @@ static void import_marks(char *input_file)
                 if (last_idnum < mark)
                         last_idnum = mark;
 
-                type = sha1_object_info(oid.hash, NULL);
+                type = oid_object_info(&oid, NULL);
                 if (type < 0)
                         die("object not found: %s", oid_to_hex(&oid));
 
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 6d73656a48..8295f92b3e 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -637,7 +637,7 @@ static int update_local_ref(struct ref *ref,
         struct branch *current_branch = branch_get(NULL);
         const char *pretty_ref = prettify_refname(ref->name);
 
-        type = sha1_object_info(ref->new_oid.hash, NULL);
+        type = oid_object_info(&ref->new_oid, NULL);
         if (type < 0)
                 die(_("object %s not found"), oid_to_hex(&ref->new_oid));
 
@@ -708,9 +708,9 @@ static int update_local_ref(struct ref *ref,
         if (in_merge_bases(current, updated)) {
                 struct strbuf quickref = STRBUF_INIT;
                 int r;
-                strbuf_add_unique_abbrev(&quickref, current->object.oid.hash, DEFAULT_ABBREV);
+                strbuf_add_unique_abbrev(&quickref, &current->object.oid, DEFAULT_ABBREV);
                 strbuf_addstr(&quickref, "..");
-                strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash, DEFAULT_ABBREV);
+                strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV);
                 if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
                     (recurse_submodules != RECURSE_SUBMODULES_ON))
                         check_for_new_submodule_commits(&ref->new_oid);
@@ -723,9 +723,9 @@ static int update_local_ref(struct ref *ref,
         } else if (force || ref->force) {
                 struct strbuf quickref = STRBUF_INIT;
                 int r;
-                strbuf_add_unique_abbrev(&quickref, current->object.oid.hash, DEFAULT_ABBREV);
+                strbuf_add_unique_abbrev(&quickref, &current->object.oid, DEFAULT_ABBREV);
                 strbuf_addstr(&quickref, "...");
-                strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash, DEFAULT_ABBREV);
+                strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV);
                 if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
                     (recurse_submodules != RECURSE_SUBMODULES_ON))
                         check_for_new_submodule_commits(&ref->new_oid);
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 8e8a15ea4a..bd680be687 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -485,10 +485,10 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
         struct strbuf tagbuf = STRBUF_INIT;
 
         for (i = 0; i < origins.nr; i++) {
-                unsigned char *sha1 = origins.items[i].util;
+                struct object_id *oid = origins.items[i].util;
                 enum object_type type;
                 unsigned long size, len;
-                char *buf = read_sha1_file(sha1, &type, &size);
+                char *buf = read_object_file(oid, &type, &size);
                 struct strbuf sig = STRBUF_INIT;
 
                 if (!buf || type != OBJ_TAG)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index ef78c6c00c..0922558683 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -65,7 +65,7 @@ static const char *printable_type(struct object *obj)
         const char *ret;
 
         if (obj->type == OBJ_NONE) {
-                enum object_type type = sha1_object_info(obj->oid.hash, NULL);
+                enum object_type type = oid_object_info(&obj->oid, NULL);
                 if (type > 0)
                         object_as_type(obj, type, 0);
         }
@@ -513,7 +513,7 @@ static struct object *parse_loose_object(const struct object_id *oid,
         unsigned long size;
         int eaten;
 
-        if (read_loose_object(path, oid->hash, &type, &size, &contents) < 0)
+        if (read_loose_object(path, oid, &type, &size, &contents) < 0)
                 return NULL;
 
         if (!contents && type != OBJ_BLOB)
diff --git a/builtin/grep.c b/builtin/grep.c
index 789a89133a..668cb8050a 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -306,7 +306,7 @@ static void *lock_and_read_oid_file(const struct object_id *oid, enum object_typ
         void *data;
 
         grep_read_lock();
-        data = read_sha1_file(oid->hash, type, size);
+        data = read_object_file(oid, type, size);
         grep_read_unlock();
         return data;
 }
@@ -452,7 +452,7 @@ static int grep_submodule(struct grep_opt *opt, struct repository *superproject,
                 object = parse_object_or_die(oid, oid_to_hex(oid));
 
                 grep_read_lock();
-                data = read_object_with_reference(object->oid.hash, tree_type,
+                data = read_object_with_reference(&object->oid, tree_type,
                                                   &size, NULL);
                 grep_read_unlock();
 
@@ -614,7 +614,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
                 int hit, len;
 
                 grep_read_lock();
-                data = read_object_with_reference(obj->oid.hash, tree_type,
+                data = read_object_with_reference(&obj->oid, tree_type,
                                                   &size, NULL);
                 grep_read_unlock();
 
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index bda84a92ef..657a5dda06 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -59,7 +59,7 @@ struct ofs_delta_entry {
 };
 
 struct ref_delta_entry {
-        unsigned char sha1[20];
+        struct object_id oid;
         int obj_no;
 };
 
@@ -222,7 +222,7 @@ static unsigned check_object(struct object *obj)
 
         if (!(obj->flags & FLAG_CHECKED)) {
                 unsigned long size;
-                int type = sha1_object_info(obj->oid.hash, &size);
+                int type = oid_object_info(&obj->oid, &size);
                 if (type <= 0)
                         die(_("did not receive expected object %s"),
                               oid_to_hex(&obj->oid));
@@ -672,18 +672,18 @@ static void find_ofs_delta_children(off_t offset,
         *last_index = last;
 }
 
-static int compare_ref_delta_bases(const unsigned char *sha1,
-                                   const unsigned char *sha2,
+static int compare_ref_delta_bases(const struct object_id *oid1,
+                                   const struct object_id *oid2,
                                    enum object_type type1,
                                    enum object_type type2)
 {
         int cmp = type1 - type2;
         if (cmp)
                 return cmp;
-        return hashcmp(sha1, sha2);
+        return oidcmp(oid1, oid2);
 }
 
-static int find_ref_delta(const unsigned char *sha1, enum object_type type)
+static int find_ref_delta(const struct object_id *oid, enum object_type type)
 {
         int first = 0, last = nr_ref_deltas;
 
@@ -692,7 +692,7 @@ static int find_ref_delta(const unsigned char *sha1, enum object_type type)
                 struct ref_delta_entry *delta = &ref_deltas[next];
                 int cmp;
 
-                cmp = compare_ref_delta_bases(sha1, delta->sha1,
+                cmp = compare_ref_delta_bases(oid, &delta->oid,
                                               type, objects[delta->obj_no].type);
                 if (!cmp)
                         return next;
@@ -705,11 +705,11 @@ static int find_ref_delta(const unsigned char *sha1, enum object_type type)
         return -first-1;
 }
 
-static void find_ref_delta_children(const unsigned char *sha1,
+static void find_ref_delta_children(const struct object_id *oid,
                                     int *first_index, int *last_index,
                                     enum object_type type)
 {
-        int first = find_ref_delta(sha1, type);
+        int first = find_ref_delta(oid, type);
         int last = first;
         int end = nr_ref_deltas - 1;
 
@@ -718,9 +718,9 @@ static void find_ref_delta_children(const unsigned char *sha1,
                 *last_index = -1;
                 return;
         }
-        while (first > 0 && !hashcmp(ref_deltas[first - 1].sha1, sha1))
+        while (first > 0 && !oidcmp(&ref_deltas[first - 1].oid, oid))
                 --first;
-        while (last < end && !hashcmp(ref_deltas[last + 1].sha1, sha1))
+        while (last < end && !oidcmp(&ref_deltas[last + 1].oid, oid))
                 ++last;
         *first_index = first;
         *last_index = last;
@@ -772,7 +772,7 @@ static int check_collison(struct object_entry *entry)
 
         memset(&data, 0, sizeof(data));
         data.entry = entry;
-        data.st = open_istream(entry->idx.oid.hash, &type, &size, NULL);
+        data.st = open_istream(&entry->idx.oid, &type, &size, NULL);
         if (!data.st)
                 return -1;
         if (size != entry->size || type != entry->type)
@@ -811,12 +811,12 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
                 enum object_type has_type;
                 unsigned long has_size;
                 read_lock();
-                has_type = sha1_object_info(oid->hash, &has_size);
+                has_type = oid_object_info(oid, &has_size);
                 if (has_type < 0)
                         die(_("cannot read existing object info %s"), oid_to_hex(oid));
                 if (has_type != type || has_size != size)
                         die(_("SHA1 COLLISION FOUND WITH %s !"), oid_to_hex(oid));
-                has_data = read_sha1_file(oid->hash, &has_type, &has_size);
+                has_data = read_object_file(oid, &has_type, &has_size);
                 read_unlock();
                 if (!data)
                         data = new_data = get_data_from_pack(obj_entry);
@@ -992,7 +992,7 @@ static struct base_data *find_unresolved_deltas_1(struct base_data *base,
                                                   struct base_data *prev_base)
 {
         if (base->ref_last == -1 && base->ofs_last == -1) {
-                find_ref_delta_children(base->obj->idx.oid.hash,
+                find_ref_delta_children(&base->obj->idx.oid,
                                         &base->ref_first, &base->ref_last,
                                         OBJ_REF_DELTA);
 
@@ -1076,7 +1076,7 @@ static int compare_ref_delta_entry(const void *a, const void *b)
         const struct ref_delta_entry *delta_a = a;
         const struct ref_delta_entry *delta_b = b;
 
-        return hashcmp(delta_a->sha1, delta_b->sha1);
+        return oidcmp(&delta_a->oid, &delta_b->oid);
 }
 
 static void resolve_base(struct object_entry *obj)
@@ -1142,7 +1142,7 @@ static void parse_pack_objects(unsigned char *hash)
                         ofs_delta++;
                 } else if (obj->type == OBJ_REF_DELTA) {
                         ALLOC_GROW(ref_deltas, nr_ref_deltas + 1, ref_deltas_alloc);
-                        hashcpy(ref_deltas[nr_ref_deltas].sha1, ref_delta_oid.hash);
+                        oidcpy(&ref_deltas[nr_ref_deltas].oid, &ref_delta_oid);
                         ref_deltas[nr_ref_deltas].obj_no = i;
                         nr_ref_deltas++;
                 } else if (!data) {
@@ -1374,14 +1374,15 @@ static void fix_unresolved_deltas(struct hashfile *f)
 
                 if (objects[d->obj_no].real_type != OBJ_REF_DELTA)
                         continue;
-                base_obj->data = read_sha1_file(d->sha1, &type, &base_obj->size);
+                base_obj->data = read_object_file(&d->oid, &type,
+                                                  &base_obj->size);
                 if (!base_obj->data)
                         continue;
 
-                if (check_sha1_signature(d->sha1, base_obj->data,
+                if (check_object_signature(&d->oid, base_obj->data,
                                 base_obj->size, type_name(type)))
-                        die(_("local object %s is corrupt"), sha1_to_hex(d->sha1));
-                base_obj->obj = append_obj_to_pack(f, d->sha1,
+                        die(_("local object %s is corrupt"), oid_to_hex(&d->oid));
+                base_obj->obj = append_obj_to_pack(f, d->oid.hash,
                                         base_obj->data, base_obj->size, type);
                 find_unresolved_deltas(base_obj);
                 display_progress(progress, nr_resolved_deltas);
diff --git a/builtin/log.c b/builtin/log.c
index 94ee177d56..71f68a3e4f 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -518,7 +518,7 @@ static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
 {
         unsigned long size;
         enum object_type type;
-        char *buf = read_sha1_file(oid->hash, &type, &size);
+        char *buf = read_object_file(oid, &type, &size);
         int offset = 0;
 
         if (!buf)
@@ -541,7 +541,7 @@ static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
         return 0;
 }
 
-static int show_tree_object(const unsigned char *sha1,
+static int show_tree_object(const struct object_id *oid,
                 struct strbuf *base,
                 const char *pathname, unsigned mode, int stage, void *context)
 {
@@ -1873,12 +1873,12 @@ static void print_commit(char sign, struct commit *commit, int verbose,
 {
         if (!verbose) {
                 fprintf(file, "%c %s\n", sign,
-                       find_unique_abbrev(commit->object.oid.hash, abbrev));
+                       find_unique_abbrev(&commit->object.oid, abbrev));
         } else {
                 struct strbuf buf = STRBUF_INIT;
                 pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);
                 fprintf(file, "%c %s %s\n", sign,
-                       find_unique_abbrev(commit->object.oid.hash, abbrev),
+                       find_unique_abbrev(&commit->object.oid, abbrev),
                        buf.buf);
                 strbuf_release(&buf);
         }
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 2fc836e330..a71f6bd088 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -240,7 +240,7 @@ static void show_ce(struct repository *repo, struct dir_struct *dir,
                         printf("%s%06o %s %d\t",
                                tag,
                                ce->ce_mode,
-                               find_unique_abbrev(ce->oid.hash, abbrev),
+                               find_unique_abbrev(&ce->oid, abbrev),
                                ce_stage(ce));
                 }
                 write_eolinfo(repo->index, ce, fullname);
@@ -271,7 +271,7 @@ static void show_ru_info(const struct index_state *istate)
                         if (!ui->mode[i])
                                 continue;
                         printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i],
-                               find_unique_abbrev(ui->sha1[i], abbrev),
+                               find_unique_abbrev(&ui->oid[i], abbrev),
                                i + 1);
                         write_name(path);
                 }
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index ef965408e8..d44b4f9c27 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -60,7 +60,7 @@ static int show_recursive(const char *base, int baselen, const char *pathname)
         return 0;
 }
 
-static int show_tree(const unsigned char *sha1, struct strbuf *base,
+static int show_tree(const struct object_id *oid, struct strbuf *base,
                 const char *pathname, unsigned mode, int stage, void *context)
 {
         int retval = 0;
@@ -94,7 +94,7 @@ static int show_tree(const unsigned char *sha1, struct strbuf *base,
                         char size_text[24];
                         if (!strcmp(type, blob_type)) {
                                 unsigned long size;
-                                if (sha1_object_info(sha1, &size) == OBJ_BAD)
+                                if (oid_object_info(oid, &size) == OBJ_BAD)
                                         xsnprintf(size_text, sizeof(size_text),
                                                   "BAD");
                                 else
@@ -103,11 +103,11 @@ static int show_tree(const unsigned char *sha1, struct strbuf *base,
                         } else
                                 xsnprintf(size_text, sizeof(size_text), "-");
                         printf("%06o %s %s %7s\t", mode, type,
-                               find_unique_abbrev(sha1, abbrev),
+                               find_unique_abbrev(oid, abbrev),
                                size_text);
                 } else
                         printf("%06o %s %s\t", mode, type,
-                               find_unique_abbrev(sha1, abbrev));
+                               find_unique_abbrev(oid, abbrev));
         }
         baselen = base->len;
         strbuf_addstr(base, pathname);
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index d01ddecf66..32736e0b10 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -60,7 +60,7 @@ static void *result(struct merge_list *entry, unsigned long *size)
         const char *path = entry->path;
 
         if (!entry->stage)
-                return read_sha1_file(entry->blob->object.oid.hash, &type, size);
+                return read_object_file(&entry->blob->object.oid, &type, size);
         base = NULL;
         if (entry->stage == 1) {
                 base = entry->blob;
@@ -82,7 +82,8 @@ static void *origin(struct merge_list *entry, unsigned long *size)
         enum object_type type;
         while (entry) {
                 if (entry->stage == 2)
-                        return read_sha1_file(entry->blob->object.oid.hash, &type, size);
+                        return read_object_file(&entry->blob->object.oid,
+                                                &type, size);
                 entry = entry->link;
         }
         return NULL;
diff --git a/builtin/merge.c b/builtin/merge.c
index ee050a47f3..8746c5e3e8 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -639,7 +639,7 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head,
 
 static void write_tree_trivial(struct object_id *oid)
 {
-        if (write_cache_as_tree(oid->hash, 0, NULL))
+        if (write_cache_as_tree(oid, 0, NULL))
                 die(_("git write-tree failed to write a tree"));
 }
 
@@ -1324,7 +1324,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 
                         check_commit_signature(commit, &signature_check);
 
-                        find_unique_abbrev_r(hex, commit->object.oid.hash, DEFAULT_ABBREV);
+                        find_unique_abbrev_r(hex, &commit->object.oid, DEFAULT_ABBREV);
                         switch (signature_check.result) {
                         case 'G':
                                 break;
@@ -1417,9 +1417,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 
                 if (verbosity >= 0) {
                         printf(_("Updating %s..%s\n"),
-                               find_unique_abbrev(head_commit->object.oid.hash,
+                               find_unique_abbrev(&head_commit->object.oid,
                                                   DEFAULT_ABBREV),
-                               find_unique_abbrev(remoteheads->item->object.oid.hash,
+                               find_unique_abbrev(&remoteheads->item->object.oid,
                                                   DEFAULT_ABBREV));
                 }
                 strbuf_addstr(&msg, "Fast-forward");
diff --git a/builtin/mktag.c b/builtin/mktag.c
index beb552847b..9f5a50a8fd 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -18,17 +18,17 @@
 /*
  * We refuse to tag something we can't verify. Just because.
  */
-static int verify_object(const unsigned char *sha1, const char *expected_type)
+static int verify_object(const struct object_id *oid, const char *expected_type)
 {
         int ret = -1;
         enum object_type type;
         unsigned long size;
-        void *buffer = read_sha1_file(sha1, &type, &size);
-        const unsigned char *repl = lookup_replace_object(sha1);
+        void *buffer = read_object_file(oid, &type, &size);
+        const struct object_id *repl = lookup_replace_object(oid);
 
         if (buffer) {
                 if (type == type_from_string(expected_type))
-                        ret = check_sha1_signature(repl, buffer, size, expected_type);
+                        ret = check_object_signature(repl, buffer, size, expected_type);
                 free(buffer);
         }
         return ret;
@@ -38,8 +38,8 @@ static int verify_tag(char *buffer, unsigned long size)
 {
         int typelen;
         char type[20];
-        unsigned char sha1[20];
-        const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb;
+        struct object_id oid;
+        const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
         size_t len;
 
         if (size < 84)
@@ -52,11 +52,11 @@ static int verify_tag(char *buffer, unsigned long size)
         if (memcmp(object, "object ", 7))
                 return error("char%d: does not start with \"object \"", 0);
 
-        if (get_sha1_hex(object + 7, sha1))
+        if (parse_oid_hex(object + 7, &oid, &p))
                 return error("char%d: could not get SHA1 hash", 7);
 
         /* Verify type line */
-        type_line = object + 48;
+        type_line = p + 1;
         if (memcmp(type_line - 1, "\ntype ", 6))
                 return error("char%d: could not find \"\\ntype \"", 47);
 
@@ -80,8 +80,8 @@ static int verify_tag(char *buffer, unsigned long size)
         type[typelen] = 0;
 
         /* Verify that the object matches */
-        if (verify_object(sha1, type))
-                return error("char%d: could not verify object %s", 7, sha1_to_hex(sha1));
+        if (verify_object(&oid, type))
+                return error("char%d: could not verify object %s", 7, oid_to_hex(&oid));
 
         /* Verify the tag-name: we don't allow control characters or spaces in it */
         tag_line += 4;
diff --git a/builtin/mktree.c b/builtin/mktree.c
index f5f3c0eea1..263c530315 100644
--- a/builtin/mktree.c
+++ b/builtin/mktree.c
@@ -10,13 +10,13 @@
 
 static struct treeent {
         unsigned mode;
-        unsigned char sha1[20];
+        struct object_id oid;
         int len;
         char name[FLEX_ARRAY];
 } **entries;
 static int alloc, used;
 
-static void append_to_tree(unsigned mode, unsigned char *sha1, char *path)
+static void append_to_tree(unsigned mode, struct object_id *oid, char *path)
 {
         struct treeent *ent;
         size_t len = strlen(path);
@@ -26,7 +26,7 @@ static void append_to_tree(unsigned mode, unsigned char *sha1, char *path)
         FLEX_ALLOC_MEM(ent, name, path, len);
         ent->mode = mode;
         ent->len = len;
-        hashcpy(ent->sha1, sha1);
+        oidcpy(&ent->oid, oid);
 
         ALLOC_GROW(entries, used + 1, alloc);
         entries[used++] = ent;
@@ -54,7 +54,7 @@ static void write_tree(struct object_id *oid)
         for (i = 0; i < used; i++) {
                 struct treeent *ent = entries[i];
                 strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0');
-                strbuf_add(&buf, ent->sha1, 20);
+                strbuf_add(&buf, ent->oid.hash, the_hash_algo->rawsz);
         }
 
         write_object_file(buf.buf, buf.len, tree_type, oid);
@@ -69,11 +69,12 @@ static const char *mktree_usage[] = {
 static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_missing)
 {
         char *ptr, *ntr;
+        const char *p;
         unsigned mode;
         enum object_type mode_type; /* object type derived from mode */
         enum object_type obj_type; /* object type derived from sha */
         char *path, *to_free = NULL;
-        unsigned char sha1[20];
+        struct object_id oid;
 
         ptr = buf;
         /*
@@ -85,9 +86,8 @@ static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_miss
                 die("input format error: %s", buf);
         ptr = ntr + 1; /* type */
         ntr = strchr(ptr, ' ');
-        if (!ntr || buf + len <= ntr + 40 ||
-            ntr[41] != '\t' ||
-            get_sha1_hex(ntr + 1, sha1))
+        if (!ntr || parse_oid_hex(ntr + 1, &oid, &p) ||
+            *p != '\t')
                 die("input format error: %s", buf);
 
         /* It is perfectly normal if we do not have a commit from a submodule */
@@ -116,12 +116,12 @@ static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_miss
         }
 
         /* Check the type of object identified by sha1 */
-        obj_type = sha1_object_info(sha1, NULL);
+        obj_type = oid_object_info(&oid, NULL);
         if (obj_type < 0) {
                 if (allow_missing) {
                         ; /* no problem - missing objects are presumed to be of the right type */
                 } else {
-                        die("entry '%s' object %s is unavailable", path, sha1_to_hex(sha1));
+                        die("entry '%s' object %s is unavailable", path, oid_to_hex(&oid));
                 }
         } else {
                 if (obj_type != mode_type) {
@@ -131,11 +131,11 @@ static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_miss
                          * because the new tree entry will never be correct.
                          */
                         die("entry '%s' object %s is a %s but specified type was (%s)",
-                                path, sha1_to_hex(sha1), type_name(obj_type), type_name(mode_type));
+                                path, oid_to_hex(&oid), type_name(obj_type), type_name(mode_type));
                 }
         }
 
-        append_to_tree(mode, sha1, path);
+        append_to_tree(mode, &oid, path);
         free(to_free);
 }
 
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 9e088ebd11..387ddf85d2 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -328,7 +328,7 @@ static void show_name(const struct object *obj,
         else if (allow_undefined)
                 printf("undefined\n");
         else if (always)
-                printf("%s\n", find_unique_abbrev(oid->hash, DEFAULT_ABBREV));
+                printf("%s\n", find_unique_abbrev(oid, DEFAULT_ABBREV));
         else
                 die("cannot describe '%s'", oid_to_hex(oid));
         strbuf_release(&buf);
diff --git a/builtin/notes.c b/builtin/notes.c
index 6d2fda4a7d..921e08d5bf 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -118,11 +118,11 @@ static int list_each_note(const struct object_id *object_oid,
         return 0;
 }
 
-static void copy_obj_to_fd(int fd, const unsigned char *sha1)
+static void copy_obj_to_fd(int fd, const struct object_id *oid)
 {
         unsigned long size;
         enum object_type type;
-        char *buf = read_sha1_file(sha1, &type, &size);
+        char *buf = read_object_file(oid, &type, &size);
         if (buf) {
                 if (size)
                         write_or_die(fd, buf, size);
@@ -162,7 +162,7 @@ static void write_commented_object(int fd, const struct object_id *object)
 }
 
 static void prepare_note_data(const struct object_id *object, struct note_data *d,
-                const unsigned char *old_note)
+                const struct object_id *old_note)
 {
         if (d->use_editor || !d->given) {
                 int fd;
@@ -253,7 +253,7 @@ static int parse_reuse_arg(const struct option *opt, const char *arg, int unset)
 
         if (get_oid(arg, &object))
                 die(_("failed to resolve '%s' as a valid ref."), arg);
-        if (!(buf = read_sha1_file(object.hash, &type, &len))) {
+        if (!(buf = read_object_file(&object, &type, &len))) {
                 free(buf);
                 die(_("failed to read object '%s'."), arg);
         }
@@ -457,7 +457,7 @@ static int add(int argc, const char **argv, const char *prefix)
                         oid_to_hex(&object));
         }
 
-        prepare_note_data(&object, &d, note ? note->hash : NULL);
+        prepare_note_data(&object, &d, note);
         if (d.buf.len || allow_empty) {
                 write_note_data(&d, &new_note);
                 if (add_note(t, &object, &new_note, combine_notes_overwrite))
@@ -602,13 +602,13 @@ static int append_edit(int argc, const char **argv, const char *prefix)
         t = init_notes_check(argv[0], NOTES_INIT_WRITABLE);
         note = get_note(t, &object);
 
-        prepare_note_data(&object, &d, edit && note ? note->hash : NULL);
+        prepare_note_data(&object, &d, edit && note ? note : NULL);
 
         if (note && !edit) {
                 /* Append buf to previous note contents */
                 unsigned long size;
                 enum object_type type;
-                char *prev_buf = read_sha1_file(note->hash, &type, &size);
+                char *prev_buf = read_object_file(note, &type, &size);
 
                 strbuf_grow(&d.buf, size + 1);
                 if (d.buf.len && prev_buf && size)
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index e9d3cfb9e3..e7e673266e 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -122,11 +122,10 @@ static void *get_delta(struct object_entry *entry)
         void *buf, *base_buf, *delta_buf;
         enum object_type type;
 
-        buf = read_sha1_file(entry->idx.oid.hash, &type, &size);
+        buf = read_object_file(&entry->idx.oid, &type, &size);
         if (!buf)
                 die("unable to read %s", oid_to_hex(&entry->idx.oid));
-        base_buf = read_sha1_file(entry->delta->idx.oid.hash, &type,
-                                  &base_size);
+        base_buf = read_object_file(&entry->delta->idx.oid, &type, &base_size);
         if (!base_buf)
                 die("unable to read %s",
                     oid_to_hex(&entry->delta->idx.oid));
@@ -267,11 +266,10 @@ static unsigned long write_no_reuse_object(struct hashfile *f, struct object_ent
         if (!usable_delta) {
                 if (entry->type == OBJ_BLOB &&
                     entry->size > big_file_threshold &&
-                    (st = open_istream(entry->idx.oid.hash, &type, &size, NULL)) != NULL)
+                    (st = open_istream(&entry->idx.oid, &type, &size, NULL)) != NULL)
                         buf = NULL;
                 else {
-                        buf = read_sha1_file(entry->idx.oid.hash, &type,
-                                             &size);
+                        buf = read_object_file(&entry->idx.oid, &type, &size);
                         if (!buf)
                                 die(_("unable to read %s"),
                                     oid_to_hex(&entry->idx.oid));
@@ -1190,7 +1188,7 @@ static struct pbase_tree_cache *pbase_tree_get(const struct object_id *oid)
         /* Did not find one.  Either we got a bogus request or
          * we need to read and perhaps cache.
          */
-        data = read_sha1_file(oid->hash, &type, &size);
+        data = read_object_file(oid, &type, &size);
         if (!data)
                 return NULL;
         if (type != OBJ_TREE) {
@@ -1351,7 +1349,7 @@ static void add_preferred_base(struct object_id *oid)
         if (window <= num_preferred_base++)
                 return;
 
-        data = read_object_with_reference(oid->hash, tree_type, &size, tree_oid.hash);
+        data = read_object_with_reference(oid, tree_type, &size, &tree_oid);
         if (!data)
                 return;
 
@@ -1516,7 +1514,7 @@ static void check_object(struct object_entry *entry)
                 unuse_pack(&w_curs);
         }
 
-        entry->type = sha1_object_info(entry->idx.oid.hash, &entry->size);
+        entry->type = oid_object_info(&entry->idx.oid, &entry->size);
         /*
          * The error condition is checked in prepare_pack().  This is
          * to permit a missing preferred base object to be ignored
@@ -1578,8 +1576,7 @@ static void drop_reused_delta(struct object_entry *entry)
                  * And if that fails, the error will be recorded in entry->type
                  * and dealt with in prepare_pack().
                  */
-                entry->type = sha1_object_info(entry->idx.oid.hash,
-                                               &entry->size);
+                entry->type = oid_object_info(&entry->idx.oid, &entry->size);
         }
 }
 
@@ -1871,8 +1868,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
         /* Load data if not already done */
         if (!trg->data) {
                 read_lock();
-                trg->data = read_sha1_file(trg_entry->idx.oid.hash, &type,
-                                           &sz);
+                trg->data = read_object_file(&trg_entry->idx.oid, &type, &sz);
                 read_unlock();
                 if (!trg->data)
                         die("object %s cannot be read",
@@ -1885,8 +1881,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
         }
         if (!src->data) {
                 read_lock();
-                src->data = read_sha1_file(src_entry->idx.oid.hash, &type,
-                                           &sz);
+                src->data = read_object_file(&src_entry->idx.oid, &type, &sz);
                 read_unlock();
                 if (!src->data) {
                         if (src_entry->preferred_base) {
@@ -2709,7 +2704,7 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
 static int add_loose_object(const struct object_id *oid, const char *path,
                             void *data)
 {
-        enum object_type type = sha1_object_info(oid->hash, NULL);
+        enum object_type type = oid_object_info(oid, NULL);
 
         if (type < 0) {
                 warning("loose object at %s could not be examined", path);
diff --git a/builtin/prune.c b/builtin/prune.c
index 4394d01c93..38ced18dad 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -50,7 +50,7 @@ static int prune_object(const struct object_id *oid, const char *fullpath,
         if (st.st_mtime > expire)
                 return 0;
         if (show_only || verbose) {
-                enum object_type type = sha1_object_info(oid->hash, NULL);
+                enum object_type type = oid_object_info(oid, NULL);
                 printf("%s %s\n", oid_to_hex(oid),
                        (type > 0) ? type_name(type) : "unknown");
         }
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 75e7f18ace..2bf7f2d1a3 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -1242,11 +1242,11 @@ static void check_aliased_update(struct command *cmd, struct string_list *list)
         rp_error("refusing inconsistent update between symref '%s' (%s..%s) and"
                  " its target '%s' (%s..%s)",
                  cmd->ref_name,
-                 find_unique_abbrev(cmd->old_oid.hash, DEFAULT_ABBREV),
-                 find_unique_abbrev(cmd->new_oid.hash, DEFAULT_ABBREV),
+                 find_unique_abbrev(&cmd->old_oid, DEFAULT_ABBREV),
+                 find_unique_abbrev(&cmd->new_oid, DEFAULT_ABBREV),
                  dst_cmd->ref_name,
-                 find_unique_abbrev(dst_cmd->old_oid.hash, DEFAULT_ABBREV),
-                 find_unique_abbrev(dst_cmd->new_oid.hash, DEFAULT_ABBREV));
+                 find_unique_abbrev(&dst_cmd->old_oid, DEFAULT_ABBREV),
+                 find_unique_abbrev(&dst_cmd->new_oid, DEFAULT_ABBREV));
 
         cmd->error_string = dst_cmd->error_string =
                 "inconsistent aliased update";
diff --git a/builtin/reflog.c b/builtin/reflog.c
index 4719a5354c..a89bd1dd25 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -75,7 +75,7 @@ static int tree_is_complete(const struct object_id *oid)
         if (!tree->buffer) {
                 enum object_type type;
                 unsigned long size;
-                void *data = read_sha1_file(oid->hash, &type, &size);
+                void *data = read_object_file(oid, &type, &size);
                 if (!data) {
                         tree->object.flags |= INCOMPLETE;
                         return 0;
diff --git a/builtin/replace.c b/builtin/replace.c
index 482f12018f..935647be6b 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -53,8 +53,8 @@ static int show_reference(const char *refname, const struct object_id *oid,
                         if (get_oid(refname, &object))
                                 return error("Failed to resolve '%s' as a valid ref.", refname);
 
-                        obj_type = sha1_object_info(object.hash, NULL);
-                        repl_type = sha1_object_info(oid->hash, NULL);
+                        obj_type = oid_object_info(&object, NULL);
+                        repl_type = oid_object_info(oid, NULL);
 
                         printf("%s (%s) -> %s (%s)\n", refname, type_name(obj_type),
                                oid_to_hex(oid), type_name(repl_type));
@@ -162,8 +162,8 @@ static int replace_object_oid(const char *object_ref,
         struct ref_transaction *transaction;
         struct strbuf err = STRBUF_INIT;
 
-        obj_type = sha1_object_info(object->hash, NULL);
-        repl_type = sha1_object_info(repl->hash, NULL);
+        obj_type = oid_object_info(object, NULL);
+        repl_type = oid_object_info(repl, NULL);
         if (!force && obj_type != repl_type)
                 die("Objects must be of the same type.\n"
                     "'%s' points to a replaced object of type '%s'\n"
@@ -290,7 +290,7 @@ static int edit_and_replace(const char *object_ref, int force, int raw)
         if (get_oid(object_ref, &old_oid) < 0)
                 die("Not a valid object name: '%s'", object_ref);
 
-        type = sha1_object_info(old_oid.hash, NULL);
+        type = oid_object_info(&old_oid, NULL);
         if (type < 0)
                 die("unable to get object type for %s", oid_to_hex(&old_oid));
 
diff --git a/builtin/reset.c b/builtin/reset.c
index 5da0f75de9..7f1c3f02a3 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -109,7 +109,7 @@ static void print_new_head_line(struct commit *commit)
         struct strbuf buf = STRBUF_INIT;
 
         printf(_("HEAD is now at %s"),
-                find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));
+                find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV));
 
         pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);
         if (buf.len > 0)
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 6f5b9b0847..fadd3ec14c 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -108,7 +108,7 @@ static void show_commit(struct commit *commit, void *data)
         if (!revs->graph)
                 fputs(get_revision_mark(revs, commit), stdout);
         if (revs->abbrev_commit && revs->abbrev)
-                fputs(find_unique_abbrev(commit->object.oid.hash, revs->abbrev),
+                fputs(find_unique_abbrev(&commit->object.oid, revs->abbrev),
                       stdout);
         else
                 fputs(oid_to_hex(&commit->object.oid), stdout);
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index a1e680b5e9..36b2087782 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -159,7 +159,7 @@ static void show_rev(int type, const struct object_id *oid, const char *name)
                 }
         }
         else if (abbrev)
-                show_with_type(type, find_unique_abbrev(oid->hash, abbrev));
+                show_with_type(type, find_unique_abbrev(oid, abbrev));
         else
                 show_with_type(type, oid_to_hex(oid));
 }
diff --git a/builtin/rm.c b/builtin/rm.c
index 4447bb4d0f..5b6fc7ee81 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -178,7 +178,7 @@ static int check_local_mod(struct object_id *head, int index_only)
                  * way as changed from the HEAD.
                  */
                 if (no_head
-                     || get_tree_entry(head->hash, name, oid.hash, &mode)
+                     || get_tree_entry(head, name, &oid, &mode)
                      || ce->ce_mode != create_ce_mode(mode)
                      || oidcmp(&ce->oid, &oid))
                         staged_changes = 1;
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index e8a4aa40cb..6c2148b71d 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -292,7 +292,7 @@ static void show_one_commit(struct commit *commit, int no_name)
                 }
                 else
                         printf("[%s] ",
-                               find_unique_abbrev(commit->object.oid.hash,
+                               find_unique_abbrev(&commit->object.oid,
                                                   DEFAULT_ABBREV));
         }
         puts(pretty_str);
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 41e5e71cad..f2eb1a7724 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -29,7 +29,7 @@ static void show_one(const char *refname, const struct object_id *oid)
         if (quiet)
                 return;
 
-        hex = find_unique_abbrev(oid->hash, abbrev);
+        hex = find_unique_abbrev(oid, abbrev);
         if (hash_only)
                 printf("%s\n", hex);
         else
@@ -39,7 +39,7 @@ static void show_one(const char *refname, const struct object_id *oid)
                 return;
 
         if (!peel_ref(refname, &peeled)) {
-                hex = find_unique_abbrev(peeled.hash, abbrev);
+                hex = find_unique_abbrev(&peeled, abbrev);
                 printf("%s %s^{}\n", hex, refname);
         }
 }
diff --git a/builtin/tag.c b/builtin/tag.c
index da186691ed..8cff6d0b72 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -99,7 +99,8 @@ static int delete_tag(const char *name, const char *ref,
 {
         if (delete_ref(NULL, ref, oid, 0))
                 return 1;
-        printf(_("Deleted tag '%s' (was %s)\n"), name, find_unique_abbrev(oid->hash, DEFAULT_ABBREV));
+        printf(_("Deleted tag '%s' (was %s)\n"), name,
+               find_unique_abbrev(oid, DEFAULT_ABBREV));
         return 0;
 }
 
@@ -167,7 +168,7 @@ static void write_tag_body(int fd, const struct object_id *oid)
         enum object_type type;
         char *buf, *sp;
 
-        buf = read_sha1_file(oid->hash, &type, &size);
+        buf = read_object_file(oid, &type, &size);
         if (!buf)
                 return;
         /* skip header */
@@ -211,7 +212,7 @@ static void create_tag(const struct object_id *object, const char *tag,
         struct strbuf header = STRBUF_INIT;
         char *path = NULL;
 
-        type = sha1_object_info(object->hash, NULL);
+        type = oid_object_info(object, NULL);
         if (type <= OBJ_NONE)
             die(_("bad object type."));
 
@@ -293,17 +294,17 @@ static void create_reflog_msg(const struct object_id *oid, struct strbuf *sb)
                 strbuf_addstr(sb, rla);
         } else {
                 strbuf_addstr(sb, "tag: tagging ");
-                strbuf_add_unique_abbrev(sb, oid->hash, DEFAULT_ABBREV);
+                strbuf_add_unique_abbrev(sb, oid, DEFAULT_ABBREV);
         }
 
         strbuf_addstr(sb, " (");
-        type = sha1_object_info(oid->hash, NULL);
+        type = oid_object_info(oid, NULL);
         switch (type) {
         default:
                 strbuf_addstr(sb, "object of unknown type");
                 break;
         case OBJ_COMMIT:
-                if ((buf = read_sha1_file(oid->hash, &type, &size)) != NULL) {
+                if ((buf = read_object_file(oid, &type, &size)) != NULL) {
                         subject_len = find_commit_subject(buf, &subject_start);
                         strbuf_insert(sb, sb->len, subject_start, subject_len);
                 } else {
@@ -558,7 +559,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
                 die("%s", err.buf);
         ref_transaction_free(transaction);
         if (force && !is_null_oid(&prev) && oidcmp(&prev, &object))
-                printf(_("Updated tag '%s' (was %s)\n"), tag, find_unique_abbrev(prev.hash, DEFAULT_ABBREV));
+                printf(_("Updated tag '%s' (was %s)\n"), tag,
+                       find_unique_abbrev(&prev, DEFAULT_ABBREV));
 
         UNLEAK(buf);
         UNLEAK(ref);
diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c
index 32e0155577..300eb59657 100644
--- a/builtin/unpack-file.c
+++ b/builtin/unpack-file.c
@@ -9,7 +9,7 @@ static char *create_temp_file(struct object_id *oid)
         unsigned long size;
         int fd;
 
-        buf = read_sha1_file(oid->hash, &type, &size);
+        buf = read_object_file(oid, &type, &size);
         if (!buf || type != OBJ_BLOB)
                 die("unable to read blob object %s", oid_to_hex(oid));
 
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 6620feec68..b7755c6cc5 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -199,7 +199,7 @@ static int check_object(struct object *obj, int type, void *data, struct fsck_op
 
         if (!(obj->flags & FLAG_OPEN)) {
                 unsigned long size;
-                int type = sha1_object_info(obj->oid.hash, &size);
+                int type = oid_object_info(&obj->oid, &size);
                 if (type != obj->type || type <= 0)
                         die("object of unexpected type");
                 obj->flags |= FLAG_WRITTEN;
@@ -423,7 +423,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
         if (resolve_against_held(nr, &base_oid, delta_data, delta_size))
                 return;
 
-        base = read_sha1_file(base_oid.hash, &type, &base_size);
+        base = read_object_file(&base_oid, &type, &base_size);
         if (!base) {
                 error("failed to read delta-pack base object %s",
                       oid_to_hex(&base_oid));
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 58d1c2d282..9625d1e10a 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -592,7 +592,7 @@ static struct cache_entry *read_one_ent(const char *which,
         int size;
         struct cache_entry *ce;
 
-        if (get_tree_entry(ent->hash, path, oid.hash, &mode)) {
+        if (get_tree_entry(ent, path, &oid, &mode)) {
                 if (which)
                         error("%s: not in %s branch.", path, which);
                 return NULL;
diff --git a/builtin/verify-commit.c b/builtin/verify-commit.c
index 05315ea7c9..dcdaada111 100644
--- a/builtin/verify-commit.c
+++ b/builtin/verify-commit.c
@@ -44,7 +44,7 @@ static int verify_commit(const char *name, unsigned flags)
         if (get_oid(name, &oid))
                 return error("commit '%s' not found.", name);
 
-        buf = read_sha1_file(oid.hash, &type, &size);
+        buf = read_object_file(&oid, &type, &size);
         if (!buf)
                 return error("%s: unable to read file.", name);
         if (type != OBJ_COMMIT)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 670555dedd..ba2cb877c3 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -502,7 +502,7 @@ static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len)
                 strbuf_addstr(&sb, "(bare)");
         else {
                 strbuf_addf(&sb, "%-*s ", abbrev_len,
-                                find_unique_abbrev(wt->head_oid.hash, DEFAULT_ABBREV));
+                                find_unique_abbrev(&wt->head_oid, DEFAULT_ABBREV));
                 if (wt->is_detached)
                         strbuf_addstr(&sb, "(detached HEAD)");
                 else if (wt->head_ref) {
@@ -527,7 +527,7 @@ static void measure_widths(struct worktree **wt, int *abbrev, int *maxlen)
 
                 if (path_len > *maxlen)
                         *maxlen = path_len;
-                sha1_len = strlen(find_unique_abbrev(wt[i]->head_oid.hash, *abbrev));
+                sha1_len = strlen(find_unique_abbrev(&wt[i]->head_oid, *abbrev));
                 if (sha1_len > *abbrev)
                         *abbrev = sha1_len;
         }
diff --git a/builtin/write-tree.c b/builtin/write-tree.c
index bd0a78aa3c..c9d3c544e7 100644
--- a/builtin/write-tree.c
+++ b/builtin/write-tree.c
@@ -19,7 +19,7 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
 {
         int flags = 0, ret;
         const char *prefix = NULL;
-        unsigned char sha1[20];
+        struct object_id oid;
         const char *me = "git-write-tree";
         struct option write_tree_options[] = {
                 OPT_BIT(0, "missing-ok", &flags, N_("allow missing objects"),
@@ -38,10 +38,10 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
         argc = parse_options(argc, argv, unused_prefix, write_tree_options,
                              write_tree_usage, 0);
 
-        ret = write_cache_as_tree(sha1, flags, prefix);
+        ret = write_cache_as_tree(&oid, flags, prefix);
         switch (ret) {
         case 0:
-                printf("%s\n", sha1_to_hex(sha1));
+                printf("%s\n", oid_to_hex(&oid));
                 break;
         case WRITE_TREE_UNREADABLE_INDEX:
                 die("%s: error reading the index", me);
diff --git a/bulk-checkin.c b/bulk-checkin.c
index 9d87eac07b..e5ce2a7954 100644
--- a/bulk-checkin.c
+++ b/bulk-checkin.c
@@ -60,17 +60,17 @@ clear_exit:
         reprepare_packed_git();
 }
 
-static int already_written(struct bulk_checkin_state *state, unsigned char sha1[])
+static int already_written(struct bulk_checkin_state *state, struct object_id *oid)
 {
         int i;
 
         /* The object may already exist in the repository */
-        if (has_sha1_file(sha1))
+        if (has_sha1_file(oid->hash))
                 return 1;
 
         /* Might want to keep the list sorted */
         for (i = 0; i < state->nr_written; i++)
-                if (!hashcmp(state->written[i]->oid.hash, sha1))
+                if (!oidcmp(&state->written[i]->oid, oid))
                         return 1;
 
         /* This is a new object we need to keep */
@@ -186,7 +186,7 @@ static void prepare_to_stream(struct bulk_checkin_state *state,
 }
 
 static int deflate_to_pack(struct bulk_checkin_state *state,
-                           unsigned char result_sha1[],
+                           struct object_id *result_oid,
                            int fd, size_t size,
                            enum object_type type, const char *path,
                            unsigned flags)
@@ -236,17 +236,17 @@ static int deflate_to_pack(struct bulk_checkin_state *state,
                 if (lseek(fd, seekback, SEEK_SET) == (off_t) -1)
                         return error("cannot seek back");
         }
-        the_hash_algo->final_fn(result_sha1, &ctx);
+        the_hash_algo->final_fn(result_oid->hash, &ctx);
         if (!idx)
                 return 0;
 
         idx->crc32 = crc32_end(state->f);
-        if (already_written(state, result_sha1)) {
+        if (already_written(state, result_oid)) {
                 hashfile_truncate(state->f, &checkpoint);
                 state->offset = checkpoint.offset;
                 free(idx);
         } else {
-                hashcpy(idx->oid.hash, result_sha1);
+                oidcpy(&idx->oid, result_oid);
                 ALLOC_GROW(state->written,
                            state->nr_written + 1,
                            state->alloc_written);
@@ -255,11 +255,11 @@ static int deflate_to_pack(struct bulk_checkin_state *state,
         return 0;
 }
 
-int index_bulk_checkin(unsigned char *sha1,
+int index_bulk_checkin(struct object_id *oid,
                        int fd, size_t size, enum object_type type,
                        const char *path, unsigned flags)
 {
-        int status = deflate_to_pack(&state, sha1, fd, size, type,
+        int status = deflate_to_pack(&state, oid, fd, size, type,
                                      path, flags);
         if (!state.plugged)
                 finish_bulk_checkin(&state);
diff --git a/bulk-checkin.h b/bulk-checkin.h
index fbd40fc98c..a85527318b 100644
--- a/bulk-checkin.h
+++ b/bulk-checkin.h
@@ -4,7 +4,7 @@
 #ifndef BULK_CHECKIN_H
 #define BULK_CHECKIN_H
 
-extern int index_bulk_checkin(unsigned char sha1[],
+extern int index_bulk_checkin(struct object_id *oid,
                               int fd, size_t size, enum object_type type,
                               const char *path, unsigned flags);
 
diff --git a/bundle.c b/bundle.c
index efe547e25f..902c9b5448 100644
--- a/bundle.c
+++ b/bundle.c
@@ -222,7 +222,7 @@ static int is_tag_in_date_range(struct object *tag, struct rev_info *revs)
         if (revs->max_age == -1 && revs->min_age == -1)
                 goto out;
 
-        buf = read_sha1_file(tag->oid.hash, &type, &size);
+        buf = read_object_file(&tag->oid, &type, &size);
         if (!buf)
                 goto out;
         line = memmem(buf, size, "\ntagger ", 8);
diff --git a/cache-tree.c b/cache-tree.c
index c52e4303df..6a555f4d43 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -320,7 +320,7 @@ static int update_one(struct cache_tree *it,
                 struct cache_tree_sub *sub = NULL;
                 const char *path, *slash;
                 int pathlen, entlen;
-                const unsigned char *sha1;
+                const struct object_id *oid;
                 unsigned mode;
                 int expected_missing = 0;
                 int contains_ita = 0;
@@ -338,7 +338,7 @@ static int update_one(struct cache_tree *it,
                                 die("cache-tree.c: '%.*s' in '%s' not found",
                                     entlen, path + baselen, path);
                         i += sub->count;
-                        sha1 = sub->cache_tree->oid.hash;
+                        oid = &sub->cache_tree->oid;
                         mode = S_IFDIR;
                         contains_ita = sub->cache_tree->entry_count < 0;
                         if (contains_ita) {
@@ -347,19 +347,19 @@ static int update_one(struct cache_tree *it,
                         }
                 }
                 else {
-                        sha1 = ce->oid.hash;
+                        oid = &ce->oid;
                         mode = ce->ce_mode;
                         entlen = pathlen - baselen;
                         i++;
                 }
 
-                if (is_null_sha1(sha1) ||
-                    (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1))) {
+                if (is_null_oid(oid) ||
+                    (mode != S_IFGITLINK && !missing_ok && !has_object_file(oid))) {
                         strbuf_release(&buffer);
                         if (expected_missing)
                                 return -1;
                         return error("invalid object %06o %s for '%.*s'",
-                                mode, sha1_to_hex(sha1), entlen+baselen, path);
+                                mode, oid_to_hex(oid), entlen+baselen, path);
                 }
 
                 /*
@@ -385,12 +385,12 @@ static int update_one(struct cache_tree *it,
                 /*
                  * "sub" can be an empty tree if all subentries are i-t-a.
                  */
-                if (contains_ita && !hashcmp(sha1, EMPTY_TREE_SHA1_BIN))
+                if (contains_ita && !oidcmp(oid, &empty_tree_oid))
                         continue;
 
                 strbuf_grow(&buffer, entlen + 100);
                 strbuf_addf(&buffer, "%o %.*s%c", mode, entlen, path + baselen, '\0');
-                strbuf_add(&buffer, sha1, 20);
+                strbuf_add(&buffer, oid->hash, the_hash_algo->rawsz);
 
 #if DEBUG
                 fprintf(stderr, "cache-tree update-one %o %.*s\n",
@@ -401,7 +401,7 @@ static int update_one(struct cache_tree *it,
         if (repair) {
                 struct object_id oid;
                 hash_object_file(buffer.buf, buffer.len, tree_type, &oid);
-                if (has_sha1_file(oid.hash))
+                if (has_object_file(&oid))
                         oidcpy(&it->oid, &oid);
                 else
                         to_invalidate = 1;
@@ -465,7 +465,7 @@ static void write_one(struct strbuf *buffer, struct cache_tree *it,
 #endif
 
         if (0 <= it->entry_count) {
-                strbuf_add(buffer, it->oid.hash, 20);
+                strbuf_add(buffer, it->oid.hash, the_hash_algo->rawsz);
         }
         for (i = 0; i < it->subtree_nr; i++) {
                 struct cache_tree_sub *down = it->down[i];
@@ -492,6 +492,7 @@ static struct cache_tree *read_one(const char **buffer, unsigned long *size_p)
         char *ep;
         struct cache_tree *it;
         int i, subtree_nr;
+        const unsigned rawsz = the_hash_algo->rawsz;
 
         it = NULL;
         /* skip name, but make sure name exists */
@@ -520,11 +521,11 @@ static struct cache_tree *read_one(const char **buffer, unsigned long *size_p)
                 goto free_return;
         buf++; size--;
         if (0 <= it->entry_count) {
-                if (size < 20)
+                if (size < rawsz)
                         goto free_return;
-                hashcpy(it->oid.hash, (const unsigned char*)buf);
-                buf += 20;
-                size -= 20;
+                memcpy(it->oid.hash, (const unsigned char*)buf, rawsz);
+                buf += rawsz;
+                size -= rawsz;
         }
 
 #if DEBUG
@@ -599,7 +600,7 @@ static struct cache_tree *cache_tree_find(struct cache_tree *it, const char *pat
         return it;
 }
 
-int write_index_as_tree(unsigned char *sha1, struct index_state *index_state, const char *index_path, int flags, const char *prefix)
+int write_index_as_tree(struct object_id *oid, struct index_state *index_state, const char *index_path, int flags, const char *prefix)
 {
         int entries, was_valid;
         struct lock_file lock_file = LOCK_INIT;
@@ -640,19 +641,19 @@ int write_index_as_tree(unsigned char *sha1, struct index_state *index_state, co
                         ret = WRITE_TREE_PREFIX_ERROR;
                         goto out;
                 }
-                hashcpy(sha1, subtree->oid.hash);
+                oidcpy(oid, &subtree->oid);
         }
         else
-                hashcpy(sha1, index_state->cache_tree->oid.hash);
+                oidcpy(oid, &index_state->cache_tree->oid);
 
 out:
         rollback_lock_file(&lock_file);
         return ret;
 }
 
-int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix)
+int write_cache_as_tree(struct object_id *oid, int flags, const char *prefix)
 {
-        return write_index_as_tree(sha1, &the_index, get_index_file(), flags, prefix);
+        return write_index_as_tree(oid, &the_index, get_index_file(), flags, prefix);
 }
 
 static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
diff --git a/cache-tree.h b/cache-tree.h
index f7b9cab7ee..cfd5328cc9 100644
--- a/cache-tree.h
+++ b/cache-tree.h
@@ -47,8 +47,8 @@ int update_main_cache_tree(int);
 #define WRITE_TREE_UNMERGED_INDEX (-2)
 #define WRITE_TREE_PREFIX_ERROR (-3)
 
-int write_index_as_tree(unsigned char *sha1, struct index_state *index_state, const char *index_path, int flags, const char *prefix);
-int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix);
+int write_index_as_tree(struct object_id *oid, struct index_state *index_state, const char *index_path, int flags, const char *prefix);
+int write_cache_as_tree(struct object_id *oid, int flags, const char *prefix);
 void prime_cache_tree(struct index_state *, struct tree *);
 
 extern int cache_tree_matches_traversal(struct cache_tree *, struct name_entry *ent, struct traverse_info *info);
diff --git a/cache.h b/cache.h
index 09f78084da..83ba2d2b03 100644
--- a/cache.h
+++ b/cache.h
@@ -955,14 +955,14 @@ extern void sha1_file_name(struct strbuf *buf, const unsigned char *sha1);
  * more calls to find_unique_abbrev are made.
  *
  * The `_r` variant writes to a buffer supplied by the caller, which must be at
- * least `GIT_SHA1_HEXSZ + 1` bytes. The return value is the number of bytes
+ * least `GIT_MAX_HEXSZ + 1` bytes. The return value is the number of bytes
  * written (excluding the NUL terminator).
  *
  * Note that while this version avoids the static buffer, it is not fully
  * reentrant, as it calls into other non-reentrant git code.
  */
-extern const char *find_unique_abbrev(const unsigned char *sha1, int len);
-extern int find_unique_abbrev_r(char *hex, const unsigned char *sha1, int len);
+extern const char *find_unique_abbrev(const struct object_id *oid, int len);
+extern int find_unique_abbrev_r(char *hex, const struct object_id *oid, int len);
 
 extern const unsigned char null_sha1[GIT_MAX_RAWSZ];
 extern const struct object_id null_oid;
@@ -1189,19 +1189,19 @@ extern char *xdg_config_home(const char *filename);
  */
 extern char *xdg_cache_home(const char *filename);
 
-extern void *read_sha1_file_extended(const unsigned char *sha1,
-                                     enum object_type *type,
-                                     unsigned long *size, int lookup_replace);
-static inline void *read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size)
+extern void *read_object_file_extended(const struct object_id *oid,
+                                       enum object_type *type,
+                                       unsigned long *size, int lookup_replace);
+static inline void *read_object_file(const struct object_id *oid, enum object_type *type, unsigned long *size)
 {
-        return read_sha1_file_extended(sha1, type, size, 1);
+        return read_object_file_extended(oid, type, size, 1);
 }
 
 /*
  * This internal function is only declared here for the benefit of
  * lookup_replace_object().  Please do not call it directly.
  */
-extern const unsigned char *do_lookup_replace_object(const unsigned char *sha1);
+extern const struct object_id *do_lookup_replace_object(const struct object_id *oid);
 
 /*
  * If object sha1 should be replaced, return the replacement object's
@@ -1209,15 +1209,15 @@ extern const unsigned char *do_lookup_replace_object(const unsigned char *sha1);
  * either sha1 or a pointer to a permanently-allocated value.  When
  * object replacement is suppressed, always return sha1.
  */
-static inline const unsigned char *lookup_replace_object(const unsigned char *sha1)
+static inline const struct object_id *lookup_replace_object(const struct object_id *oid)
 {
         if (!check_replace_refs)
-                return sha1;
-        return do_lookup_replace_object(sha1);
+                return oid;
+        return do_lookup_replace_object(oid);
 }
 
-/* Read and unpack a sha1 file into memory, write memory to a sha1 file */
-extern int sha1_object_info(const unsigned char *, unsigned long *);
+/* Read and unpack an object file into memory, write memory to an object file */
+extern int oid_object_info(const struct object_id *, unsigned long *);
 
 extern int hash_object_file(const void *buf, unsigned long len,
                             const char *type, struct object_id *oid);
@@ -1240,19 +1240,19 @@ extern void *map_sha1_file(const unsigned char *sha1, unsigned long *size);
 extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
 extern int parse_sha1_header(const char *hdr, unsigned long *sizep);
 
-extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);
+extern int check_object_signature(const struct object_id *oid, void *buf, unsigned long size, const char *type);
 
 extern int finalize_object_file(const char *tmpfile, const char *filename);
 
 /*
- * Open the loose object at path, check its sha1, and return the contents,
+ * Open the loose object at path, check its hash, and return the contents,
  * type, and size. If the object is a blob, then "contents" may return NULL,
  * to allow streaming of large blobs.
  *
  * Returns 0 on success, negative on error (details may be written to stderr).
  */
 int read_loose_object(const char *path,
-                      const unsigned char *expected_sha1,
+                      const struct object_id *expected_oid,
                       enum object_type *type,
                       unsigned long *size,
                       void **contents);
@@ -1279,7 +1279,7 @@ extern int has_object_file_with_flags(const struct object_id *oid, int flags);
  */
 extern int has_loose_object_nonlocal(const unsigned char *sha1);
 
-extern void assert_sha1_type(const unsigned char *sha1, enum object_type expect);
+extern void assert_oid_type(const struct object_id *oid, enum object_type expect);
 
 /* Helper to check and "touch" a file */
 extern int check_and_freshen_file(const char *fn, int freshen);
@@ -1435,10 +1435,10 @@ extern int df_name_compare(const char *name1, int len1, int mode1, const char *n
 extern int name_compare(const char *name1, size_t len1, const char *name2, size_t len2);
 extern int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2);
 
-extern void *read_object_with_reference(const unsigned char *sha1,
+extern void *read_object_with_reference(const struct object_id *oid,
                                         const char *required_type,
                                         unsigned long *size,
-                                        unsigned char *sha1_ret);
+                                        struct object_id *oid_ret);
 
 extern struct object *peel_to_type(const char *name, int namelen,
                                    struct object *o, enum object_type);
@@ -1779,7 +1779,7 @@ struct object_info {
 #define OBJECT_INFO_QUICK 8
 /* Do not check loose object */
 #define OBJECT_INFO_IGNORE_LOOSE 16
-extern int sha1_object_info_extended(const unsigned char *, struct object_info *, unsigned flags);
+extern int oid_object_info_extended(const struct object_id *, struct object_info *, unsigned flags);
 
 /*
  * Set this to 0 to prevent sha1_object_info_extended() from fetching missing
diff --git a/combine-diff.c b/combine-diff.c
index 1ec9af1f81..2ef495963f 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -306,7 +306,7 @@ static char *grab_blob(const struct object_id *oid, unsigned int mode,
                 *size = fill_textconv(textconv, df, &blob);
                 free_filespec(df);
         } else {
-                blob = read_sha1_file(oid->hash, &type, size);
+                blob = read_object_file(oid, &type, size);
                 if (type != OBJ_BLOB)
                         die("object '%s' is not a blob!", oid_to_hex(oid));
         }
@@ -915,11 +915,11 @@ static void show_combined_header(struct combine_diff_path *elem,
                          "", elem->path, line_prefix, c_meta, c_reset);
         printf("%s%sindex ", line_prefix, c_meta);
         for (i = 0; i < num_parent; i++) {
-                abb = find_unique_abbrev(elem->parent[i].oid.hash,
+                abb = find_unique_abbrev(&elem->parent[i].oid,
                                          abbrev);
                 printf("%s%s", i ? "," : "", abb);
         }
-        abb = find_unique_abbrev(elem->oid.hash, abbrev);
+        abb = find_unique_abbrev(&elem->oid, abbrev);
         printf("..%s%s\n", abb, c_reset);
 
         if (mode_differs) {
diff --git a/commit.c b/commit.c
index 00c99c7272..ca474a7c11 100644
--- a/commit.c
+++ b/commit.c
@@ -266,7 +266,7 @@ const void *get_commit_buffer(const struct commit *commit, unsigned long *sizep)
         if (!ret) {
                 enum object_type type;
                 unsigned long size;
-                ret = read_sha1_file(commit->object.oid.hash, &type, &size);
+                ret = read_object_file(&commit->object.oid, &type, &size);
                 if (!ret)
                         die("cannot read commit object %s",
                             oid_to_hex(&commit->object.oid));
@@ -383,7 +383,7 @@ int parse_commit_gently(struct commit *item, int quiet_on_missing)
                 return -1;
         if (item->object.parsed)
                 return 0;
-        buffer = read_sha1_file(item->object.oid.hash, &type, &size);
+        buffer = read_object_file(&item->object.oid, &type, &size);
         if (!buffer)
                 return quiet_on_missing ? -1 :
                         error("Could not read %s",
@@ -1206,7 +1206,7 @@ static void handle_signed_tag(struct commit *parent, struct commit_extra_header
         desc = merge_remote_util(parent);
         if (!desc || !desc->obj)
                 return;
-        buf = read_sha1_file(desc->obj->oid.hash, &type, &size);
+        buf = read_object_file(&desc->obj->oid, &type, &size);
         if (!buf || type != OBJ_TAG)
                 goto free_return;
         len = parse_signature(buf, size);
@@ -1517,7 +1517,7 @@ int commit_tree_extended(const char *msg, size_t msg_len,
         int encoding_is_utf8;
         struct strbuf buffer;
 
-        assert_sha1_type(tree->hash, OBJ_TREE);
+        assert_oid_type(tree, OBJ_TREE);
 
         if (memchr(msg, '\0', msg_len))
                 return error("a NUL byte in commit log message not allowed.");
diff --git a/config.c b/config.c
index b0c20e6cb8..c698988f5e 100644
--- a/config.c
+++ b/config.c
@@ -1488,7 +1488,7 @@ int git_config_from_blob_oid(config_fn_t fn,
         unsigned long size;
         int ret;
 
-        buf = read_sha1_file(oid->hash, &type, &size);
+        buf = read_object_file(oid, &type, &size);
         if (!buf)
                 return error("unable to load config blob object '%s'", name);
         if (type != OBJ_BLOB) {
diff --git a/convert.c b/convert.c
index cc562f6509..c480097a2a 100644
--- a/convert.c
+++ b/convert.c
@@ -914,7 +914,7 @@ static int ident_to_worktree(const char *path, const char *src, size_t len,
                 to_free = strbuf_detach(buf, NULL);
         hash_object_file(src, len, "blob", &oid);
 
-        strbuf_grow(buf, len + cnt * 43);
+        strbuf_grow(buf, len + cnt * (the_hash_algo->hexsz + 3));
         for (;;) {
                 /* step 1: run to the next '$' */
                 dollar = memchr(src, '$', len);
@@ -1510,7 +1510,7 @@ struct ident_filter {
         struct stream_filter filter;
         struct strbuf left;
         int state;
-        char ident[45]; /* ": x40 $" */
+        char ident[GIT_MAX_HEXSZ + 5]; /* ": x40 $" */
 };
 
 static int is_foreign_ident(const char *str)
@@ -1635,12 +1635,12 @@ static struct stream_filter_vtbl ident_vtbl = {
         ident_free_fn,
 };
 
-static struct stream_filter *ident_filter(const unsigned char *sha1)
+static struct stream_filter *ident_filter(const struct object_id *oid)
 {
         struct ident_filter *ident = xmalloc(sizeof(*ident));
 
         xsnprintf(ident->ident, sizeof(ident->ident),
-                  ": %s $", sha1_to_hex(sha1));
+                  ": %s $", oid_to_hex(oid));
         strbuf_init(&ident->left, 0);
         ident->filter.vtbl = &ident_vtbl;
         ident->state = 0;
@@ -1655,7 +1655,7 @@ static struct stream_filter *ident_filter(const unsigned char *sha1)
  * Note that you would be crazy to set CRLF, smuge/clean or ident to a
  * large binary blob you would want us not to slurp into the memory!
  */
-struct stream_filter *get_stream_filter(const char *path, const unsigned char *sha1)
+struct stream_filter *get_stream_filter(const char *path, const struct object_id *oid)
 {
         struct conv_attrs ca;
         struct stream_filter *filter = NULL;
@@ -1668,7 +1668,7 @@ struct stream_filter *get_stream_filter(const char *path, const unsigned char *s
                 return NULL;
 
         if (ca.ident)
-                filter = ident_filter(sha1);
+                filter = ident_filter(oid);
 
         if (output_eol(ca.crlf_action) == EOL_CRLF)
                 filter = cascade_filter(filter, lf_to_crlf_filter());
diff --git a/convert.h b/convert.h
index 65ab3e5167..2e9b4f49cc 100644
--- a/convert.h
+++ b/convert.h
@@ -93,7 +93,7 @@ extern int would_convert_to_git_filter_fd(const char *path);
 
 struct stream_filter; /* opaque */
 
-extern struct stream_filter *get_stream_filter(const char *path, const unsigned char *);
+extern struct stream_filter *get_stream_filter(const char *path, const struct object_id *);
 extern void free_stream_filter(struct stream_filter *);
 extern int is_null_stream_filter(struct stream_filter *);
 
diff --git a/diff.c b/diff.c
index 4c59f5f5d3..1289df4b1f 100644
--- a/diff.c
+++ b/diff.c
@@ -3638,7 +3638,7 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags)
         else {
                 enum object_type type;
                 if (size_only || (flags & CHECK_BINARY)) {
-                        type = sha1_object_info(s->oid.hash, &s->size);
+                        type = oid_object_info(&s->oid, &s->size);
                         if (type < 0)
                                 die("unable to read %s",
                                     oid_to_hex(&s->oid));
@@ -3649,7 +3649,7 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags)
                                 return 0;
                         }
                 }
-                s->data = read_sha1_file(s->oid.hash, &type, &s->size);
+                s->data = read_object_file(&s->oid, &type, &s->size);
                 if (!s->data)
                         die("unable to read %s", oid_to_hex(&s->oid));
                 s->should_free = 1;
@@ -3834,7 +3834,7 @@ static int similarity_index(struct diff_filepair *p)
 static const char *diff_abbrev_oid(const struct object_id *oid, int abbrev)
 {
         if (startup_info->have_repository)
-                return find_unique_abbrev(oid->hash, abbrev);
+                return find_unique_abbrev(oid, abbrev);
         else {
                 char *hex = oid_to_hex(oid);
                 if (abbrev < 0)
diff --git a/dir.c b/dir.c
index dedbf5d476..63a917be45 100644
--- a/dir.c
+++ b/dir.c
@@ -243,7 +243,7 @@ static int do_read_blob(const struct object_id *oid, struct oid_stat *oid_stat,
         *size_out = 0;
         *data_out = NULL;
 
-        data = read_sha1_file(oid->hash, &type, &sz);
+        data = read_object_file(oid, &type, &sz);
         if (!data || type != OBJ_BLOB) {
                 free(data);
                 return -1;
diff --git a/entry.c b/entry.c
index 6c33112aea..2101201a11 100644
--- a/entry.c
+++ b/entry.c
@@ -85,7 +85,7 @@ static int create_file(const char *path, unsigned int mode)
 static void *read_blob_entry(const struct cache_entry *ce, unsigned long *size)
 {
         enum object_type type;
-        void *blob_data = read_sha1_file(ce->oid.hash, &type, size);
+        void *blob_data = read_object_file(&ce->oid, &type, size);
 
         if (blob_data) {
                 if (type == OBJ_BLOB)
@@ -266,7 +266,7 @@ static int write_entry(struct cache_entry *ce,
 
         if (ce_mode_s_ifmt == S_IFREG) {
                 struct stream_filter *filter = get_stream_filter(ce->name,
-                                                                 ce->oid.hash);
+                                                                 &ce->oid);
                 if (filter &&
                     !streaming_write_entry(ce, path, filter,
                                            state, to_tempfile,
diff --git a/fast-import.c b/fast-import.c
index b5db5d20b1..a2e8b1d763 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1412,7 +1412,7 @@ static void load_tree(struct tree_entry *root)
                         die("Can't load tree %s", oid_to_hex(oid));
         } else {
                 enum object_type type;
-                buf = read_sha1_file(oid->hash, &type, &size);
+                buf = read_object_file(oid, &type, &size);
                 if (!buf || type != OBJ_TREE)
                         die("Can't load tree %s", oid_to_hex(oid));
         }
@@ -1913,7 +1913,7 @@ static void read_marks(void)
                         die("corrupt mark line: %s", line);
                 e = find_object(&oid);
                 if (!e) {
-                        enum object_type type = sha1_object_info(oid.hash, NULL);
+                        enum object_type type = oid_object_info(&oid, NULL);
                         if (type < 0)
                                 die("object not found: %s", oid_to_hex(&oid));
                         e = insert_object(&oid);
@@ -2443,7 +2443,7 @@ static void file_change_m(const char *p, struct branch *b)
                 enum object_type expected = S_ISDIR(mode) ?
                                                 OBJ_TREE: OBJ_BLOB;
                 enum object_type type = oe ? oe->type :
-                                        sha1_object_info(oid.hash, NULL);
+                                        oid_object_info(&oid, NULL);
                 if (type < 0)
                         die("%s not found: %s",
                                         S_ISDIR(mode) ?  "Tree" : "Blob",
@@ -2583,8 +2583,9 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa
                 oidcpy(&commit_oid, &commit_oe->idx.oid);
         } else if (!get_oid(p, &commit_oid)) {
                 unsigned long size;
-                char *buf = read_object_with_reference(commit_oid.hash,
-                        commit_type, &size, commit_oid.hash);
+                char *buf = read_object_with_reference(&commit_oid,
+                                                       commit_type, &size,
+                                                       &commit_oid);
                 if (!buf || size < 46)
                         die("Not a valid commit: %s", p);
                 free(buf);
@@ -2603,7 +2604,7 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa
                         die("Not a blob (actually a %s): %s",
                                 type_name(oe->type), command_buf.buf);
         } else if (!is_null_oid(&oid)) {
-                enum object_type type = sha1_object_info(oid.hash, NULL);
+                enum object_type type = oid_object_info(&oid, NULL);
                 if (type < 0)
                         die("Blob not found: %s", command_buf.buf);
                 if (type != OBJ_BLOB)
@@ -2653,9 +2654,8 @@ static void parse_from_existing(struct branch *b)
                 unsigned long size;
                 char *buf;
 
-                buf = read_object_with_reference(b->oid.hash,
-                                                 commit_type, &size,
-                                                 b->oid.hash);
+                buf = read_object_with_reference(&b->oid, commit_type, &size,
+                                                 &b->oid);
                 parse_from_commit(b, buf, size);
                 free(buf);
         }
@@ -2732,8 +2732,9 @@ static struct hash_list *parse_merge(unsigned int *count)
                         oidcpy(&n->oid, &oe->idx.oid);
                 } else if (!get_oid(from, &n->oid)) {
                         unsigned long size;
-                        char *buf = read_object_with_reference(n->oid.hash,
-                                commit_type, &size, n->oid.hash);
+                        char *buf = read_object_with_reference(&n->oid,
+                                                               commit_type,
+                                                               &size, &n->oid);
                         if (!buf || size < 46)
                                 die("Not a valid commit: %s", from);
                         free(buf);
@@ -2890,7 +2891,7 @@ static void parse_new_tag(const char *arg)
         } else if (!get_oid(from, &oid)) {
                 struct object_entry *oe = find_object(&oid);
                 if (!oe) {
-                        type = sha1_object_info(oid.hash, NULL);
+                        type = oid_object_info(&oid, NULL);
                         if (type < 0)
                                 die("Not a valid object: %s", from);
                 } else
@@ -2966,7 +2967,7 @@ static void cat_blob(struct object_entry *oe, struct object_id *oid)
         char *buf;
 
         if (!oe || oe->pack_id == MAX_PACK_ID) {
-                buf = read_sha1_file(oid->hash, &type, &size);
+                buf = read_object_file(oid, &type, &size);
         } else {
                 type = oe->type;
                 buf = gfi_unpack_entry(oe, &size);
@@ -3048,7 +3049,7 @@ static struct object_entry *dereference(struct object_entry *oe,
         unsigned long size;
         char *buf = NULL;
         if (!oe) {
-                enum object_type type = sha1_object_info(oid->hash, NULL);
+                enum object_type type = oid_object_info(oid, NULL);
                 if (type < 0)
                         die("object not found: %s", oid_to_hex(oid));
                 /* cache it! */
@@ -3071,7 +3072,7 @@ static struct object_entry *dereference(struct object_entry *oe,
                 buf = gfi_unpack_entry(oe, &size);
         } else {
                 enum object_type unused;
-                buf = read_sha1_file(oid->hash, &unused, &size);
+                buf = read_object_file(oid, &unused, &size);
         }
         if (!buf)
                 die("Can't load object %s", oid_to_hex(oid));
diff --git a/fsck.c b/fsck.c
index 5c8c12dde3..9218c2a643 100644
--- a/fsck.c
+++ b/fsck.c
@@ -811,7 +811,7 @@ static int fsck_tag_buffer(struct tag *tag, const char *data,
                 enum object_type type;
 
                 buffer = to_free =
-                        read_sha1_file(tag->object.oid.hash, &type, &size);
+                        read_object_file(&tag->object.oid, &type, &size);
                 if (!buffer)
                         return report(options, &tag->object,
                                 FSCK_MSG_MISSING_TAG_OBJECT,
diff --git a/grep.c b/grep.c
index 834b8eb439..65b90c10a3 100644
--- a/grep.c
+++ b/grep.c
@@ -2015,7 +2015,7 @@ static int grep_source_load_oid(struct grep_source *gs)
         enum object_type type;
 
         grep_read_lock();
-        gs->buf = read_sha1_file(gs->identifier, &type, &gs->size);
+        gs->buf = read_object_file(gs->identifier, &type, &gs->size);
         grep_read_unlock();
 
         if (!gs->buf)
diff --git a/http-push.c b/http-push.c
index 7dcd9daf62..ff82b63133 100644
--- a/http-push.c
+++ b/http-push.c
@@ -361,7 +361,7 @@ static void start_put(struct transfer_request *request)
         ssize_t size;
         git_zstream stream;
 
-        unpacked = read_sha1_file(request->obj->oid.hash, &type, &len);
+        unpacked = read_object_file(&request->obj->oid, &type, &len);
         hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", type_name(type), len) + 1;
 
         /* Set it up */
diff --git a/http-walker.c b/http-walker.c
index 07c2b1af82..f506f394ac 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -22,7 +22,7 @@ enum object_request_state {
 
 struct object_request {
         struct walker *walker;
-        unsigned char sha1[20];
+        struct object_id oid;
         struct alt_base *repo;
         enum object_request_state state;
         struct http_object_request *req;
@@ -56,7 +56,7 @@ static void start_object_request(struct walker *walker,
         struct active_request_slot *slot;
         struct http_object_request *req;
 
-        req = new_http_object_request(obj_req->repo->base, obj_req->sha1);
+        req = new_http_object_request(obj_req->repo->base, obj_req->oid.hash);
         if (req == NULL) {
                 obj_req->state = ABORTED;
                 return;
@@ -82,7 +82,7 @@ static void finish_object_request(struct object_request *obj_req)
                 return;
 
         if (obj_req->req->rename == 0)
-                walker_say(obj_req->walker, "got %s\n", sha1_to_hex(obj_req->sha1));
+                walker_say(obj_req->walker, "got %s\n", oid_to_hex(&obj_req->oid));
 }
 
 static void process_object_response(void *callback_data)
@@ -129,7 +129,7 @@ static int fill_active_slot(struct walker *walker)
         list_for_each_safe(pos, tmp, head) {
                 obj_req = list_entry(pos, struct object_request, node);
                 if (obj_req->state == WAITING) {
-                        if (has_sha1_file(obj_req->sha1))
+                        if (has_sha1_file(obj_req->oid.hash))
                                 obj_req->state = COMPLETE;
                         else {
                                 start_object_request(walker, obj_req);
@@ -148,7 +148,7 @@ static void prefetch(struct walker *walker, unsigned char *sha1)
 
         newreq = xmalloc(sizeof(*newreq));
         newreq->walker = walker;
-        hashcpy(newreq->sha1, sha1);
+        hashcpy(newreq->oid.hash, sha1);
         newreq->repo = data->alt;
         newreq->state = WAITING;
         newreq->req = NULL;
@@ -481,13 +481,13 @@ static int fetch_object(struct walker *walker, unsigned char *sha1)
 
         list_for_each(pos, head) {
                 obj_req = list_entry(pos, struct object_request, node);
-                if (!hashcmp(obj_req->sha1, sha1))
+                if (!hashcmp(obj_req->oid.hash, sha1))
                         break;
         }
         if (obj_req == NULL)
                 return error("Couldn't find request for %s in the queue", hex);
 
-        if (has_sha1_file(obj_req->sha1)) {
+        if (has_sha1_file(obj_req->oid.hash)) {
                 if (obj_req->req != NULL)
                         abort_http_object_request(obj_req->req);
                 abort_object_request(obj_req);
@@ -541,7 +541,7 @@ static int fetch_object(struct walker *walker, unsigned char *sha1)
         } else if (req->zret != Z_STREAM_END) {
                 walker->corrupt_object_found++;
                 ret = error("File %s (%s) corrupt", hex, req->url);
-        } else if (hashcmp(obj_req->sha1, req->real_sha1)) {
+        } else if (hashcmp(obj_req->oid.hash, req->real_sha1)) {
                 ret = error("File %s has bad hash", hex);
         } else if (req->rename < 0) {
                 struct strbuf buf = STRBUF_INIT;
diff --git a/line-log.c b/line-log.c
index cdc2257db5..ecdce08c4b 100644
--- a/line-log.c
+++ b/line-log.c
@@ -501,8 +501,7 @@ static void fill_blob_sha1(struct commit *commit, struct diff_filespec *spec)
         unsigned mode;
         struct object_id oid;
 
-        if (get_tree_entry(commit->object.oid.hash, spec->path,
-                           oid.hash, &mode))
+        if (get_tree_entry(&commit->object.oid, spec->path, &oid, &mode))
                 die("There is no path %s in the commit", spec->path);
         fill_filespec(spec, &oid, 1, mode);
 
diff --git a/list-objects-filter.c b/list-objects-filter.c
index 4356c45368..0ec83aaf18 100644
--- a/list-objects-filter.c
+++ b/list-objects-filter.c
@@ -117,7 +117,7 @@ static enum list_objects_filter_result filter_blobs_limit(
                 assert(obj->type == OBJ_BLOB);
                 assert((obj->flags & SEEN) == 0);
 
-                t = sha1_object_info(obj->oid.hash, &object_length);
+                t = oid_object_info(&obj->oid, &object_length);
                 if (t != OBJ_BLOB) { /* probably OBJ_NONE */
                         /*
                          * We DO NOT have the blob locally, so we cannot
diff --git a/log-tree.c b/log-tree.c
index bdf23c5f7b..d1c0bedf24 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -177,7 +177,7 @@ static void show_parents(struct commit *commit, int abbrev, FILE *file)
         struct commit_list *p;
         for (p = commit->parents; p ; p = p->next) {
                 struct commit *parent = p->item;
-                fprintf(file, " %s", find_unique_abbrev(parent->object.oid.hash, abbrev));
+                fprintf(file, " %s", find_unique_abbrev(&parent->object.oid, abbrev));
         }
 }
 
@@ -185,7 +185,7 @@ static void show_children(struct rev_info *opt, struct commit *commit, int abbre
 {
         struct commit_list *p = lookup_decoration(&opt->children, &commit->object);
         for ( ; p; p = p->next) {
-                fprintf(opt->diffopt.file, " %s", find_unique_abbrev(p->item->object.oid.hash, abbrev));
+                fprintf(opt->diffopt.file, " %s", find_unique_abbrev(&p->item->object.oid, abbrev));
         }
 }
 
@@ -558,7 +558,7 @@ void show_log(struct rev_info *opt)
 
                 if (!opt->graph)
                         put_revision_mark(opt, commit);
-                fputs(find_unique_abbrev(commit->object.oid.hash, abbrev_commit), opt->diffopt.file);
+                fputs(find_unique_abbrev(&commit->object.oid, abbrev_commit), opt->diffopt.file);
                 if (opt->print_parents)
                         show_parents(commit, abbrev_commit, opt->diffopt.file);
                 if (opt->children.name)
@@ -620,7 +620,8 @@ void show_log(struct rev_info *opt)
 
                 if (!opt->graph)
                         put_revision_mark(opt, commit);
-                fputs(find_unique_abbrev(commit->object.oid.hash, abbrev_commit),
+                fputs(find_unique_abbrev(&commit->object.oid,
+                                         abbrev_commit),
                       opt->diffopt.file);
                 if (opt->print_parents)
                         show_parents(commit, abbrev_commit, opt->diffopt.file);
@@ -628,8 +629,7 @@ void show_log(struct rev_info *opt)
                         show_children(opt, commit, abbrev_commit);
                 if (parent)
                         fprintf(opt->diffopt.file, " (from %s)",
-                               find_unique_abbrev(parent->object.oid.hash,
-                                                  abbrev_commit));
+                               find_unique_abbrev(&parent->object.oid, abbrev_commit));
                 fputs(diff_get_color_opt(&opt->diffopt, DIFF_RESET), opt->diffopt.file);
                 show_decorations(opt, commit);
                 if (opt->commit_format == CMIT_FMT_ONELINE) {
diff --git a/mailmap.c b/mailmap.c
index cb921b4db6..13f0d2884e 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -224,7 +224,7 @@ static int read_mailmap_blob(struct string_list *map,
         if (get_oid(name, &oid) < 0)
                 return 0;
 
-        buf = read_sha1_file(oid.hash, &type, &size);
+        buf = read_object_file(&oid, &type, &size);
         if (!buf)
                 return error("unable to read mailmap object at %s", name);
         if (type != OBJ_BLOB)
diff --git a/match-trees.c b/match-trees.c
index 0ca99d5162..72cc2baa3f 100644
--- a/match-trees.c
+++ b/match-trees.c
@@ -54,7 +54,7 @@ static void *fill_tree_desc_strict(struct tree_desc *desc,
         enum object_type type;
         unsigned long size;
 
-        buffer = read_sha1_file(hash->hash, &type, &size);
+        buffer = read_object_file(hash, &type, &size);
         if (!buffer)
                 die("unable to read tree (%s)", oid_to_hex(hash));
         if (type != OBJ_TREE)
@@ -180,7 +180,7 @@ static int splice_tree(const struct object_id *oid1, const char *prefix,
         if (*subpath)
                 subpath++;
 
-        buf = read_sha1_file(oid1->hash, &type, &sz);
+        buf = read_object_file(oid1, &type, &sz);
         if (!buf)
                 die("cannot read tree %s", oid_to_hex(oid1));
         init_tree_desc(&desc, buf, sz);
@@ -269,7 +269,7 @@ void shift_tree(const struct object_id *hash1,
                 if (!*del_prefix)
                         return;
 
-                if (get_tree_entry(hash2->hash, del_prefix, shifted->hash, &mode))
+                if (get_tree_entry(hash2, del_prefix, shifted, &mode))
                         die("cannot find path %s in tree %s",
                             del_prefix, oid_to_hex(hash2));
                 return;
@@ -296,12 +296,12 @@ void shift_tree_by(const struct object_id *hash1,
         unsigned candidate = 0;
 
         /* Can hash2 be a tree at shift_prefix in tree hash1? */
-        if (!get_tree_entry(hash1->hash, shift_prefix, sub1.hash, &mode1) &&
+        if (!get_tree_entry(hash1, shift_prefix, &sub1, &mode1) &&
             S_ISDIR(mode1))
                 candidate |= 1;
 
         /* Can hash1 be a tree at shift_prefix in tree hash2? */
-        if (!get_tree_entry(hash2->hash, shift_prefix, sub2.hash, &mode2) &&
+        if (!get_tree_entry(hash2, shift_prefix, &sub2, &mode2) &&
             S_ISDIR(mode2))
                 candidate |= 2;
 
diff --git a/merge-blobs.c b/merge-blobs.c
index 9b6eac22e4..fa49c17287 100644
--- a/merge-blobs.c
+++ b/merge-blobs.c
@@ -11,7 +11,7 @@ static int fill_mmfile_blob(mmfile_t *f, struct blob *obj)
         unsigned long size;
         enum object_type type;
 
-        buf = read_sha1_file(obj->object.oid.hash, &type, &size);
+        buf = read_object_file(&obj->object.oid, &type, &size);
         if (!buf)
                 return -1;
         if (type != OBJ_BLOB) {
@@ -66,7 +66,7 @@ void *merge_blobs(const char *path, struct blob *base, struct blob *our, struct
                         return NULL;
                 if (!our)
                         our = their;
-                return read_sha1_file(our->object.oid.hash, &type, size);
+                return read_object_file(&our->object.oid, &type, size);
         }
 
         if (fill_mmfile_blob(&f1, our) < 0)
diff --git a/merge-recursive.c b/merge-recursive.c
index 55d1e779a0..9c05eb7f70 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -290,7 +290,7 @@ static void output_commit_title(struct merge_options *o, struct commit *commit)
                 strbuf_addf(&o->obuf, "virtual %s\n",
                         merge_remote_util(commit)->name);
         else {
-                strbuf_add_unique_abbrev(&o->obuf, commit->object.oid.hash,
+                strbuf_add_unique_abbrev(&o->obuf, &commit->object.oid,
                                          DEFAULT_ABBREV);
                 strbuf_addch(&o->obuf, ' ');
                 if (parse_commit(commit) != 0)
@@ -402,7 +402,7 @@ struct tree *write_tree_from_memory(struct merge_options *o)
         return result;
 }
 
-static int save_files_dirs(const unsigned char *sha1,
+static int save_files_dirs(const struct object_id *oid,
                 struct strbuf *base, const char *path,
                 unsigned int mode, int stage, void *context)
 {
@@ -427,16 +427,16 @@ static void get_files_dirs(struct merge_options *o, struct tree *tree)
         read_tree_recursive(tree, "", 0, 0, &match_all, save_files_dirs, o);
 }
 
-static int get_tree_entry_if_blob(const unsigned char *tree,
+static int get_tree_entry_if_blob(struct tree *tree,
                                   const char *path,
-                                  unsigned char *hashy,
+                                  struct object_id *hashy,
                                   unsigned int *mode_o)
 {
         int ret;
 
-        ret = get_tree_entry(tree, path, hashy, mode_o);
+        ret = get_tree_entry(&tree->object.oid, path, hashy, mode_o);
         if (S_ISDIR(*mode_o)) {
-                hashcpy(hashy, null_sha1);
+                oidcpy(hashy, &null_oid);
                 *mode_o = 0;
         }
         return ret;
@@ -452,12 +452,12 @@ static struct stage_data *insert_stage_data(const char *path,
 {
         struct string_list_item *item;
         struct stage_data *e = xcalloc(1, sizeof(struct stage_data));
-        get_tree_entry_if_blob(o->object.oid.hash, path,
-                               e->stages[1].oid.hash, &e->stages[1].mode);
-        get_tree_entry_if_blob(a->object.oid.hash, path,
-                               e->stages[2].oid.hash, &e->stages[2].mode);
-        get_tree_entry_if_blob(b->object.oid.hash, path,
-                               e->stages[3].oid.hash, &e->stages[3].mode);
+        get_tree_entry_if_blob(o, path,
+                               &e->stages[1].oid, &e->stages[1].mode);
+        get_tree_entry_if_blob(a, path,
+                               &e->stages[2].oid, &e->stages[2].mode);
+        get_tree_entry_if_blob(b, path,
+                               &e->stages[3].oid, &e->stages[3].mode);
         item = string_list_insert(entries, path);
         item->util = e;
         return e;
@@ -891,7 +891,7 @@ static int update_file_flags(struct merge_options *o,
                         goto update_index;
                 }
 
-                buf = read_sha1_file(oid->hash, &type, &size);
+                buf = read_object_file(oid, &type, &size);
                 if (!buf)
                         return err(o, _("cannot read object %s '%s'"), oid_to_hex(oid), path);
                 if (type != OBJ_BLOB) {
@@ -1559,11 +1559,11 @@ static struct diff_queue_struct *get_diffpairs(struct merge_options *o,
 
 static int tree_has_path(struct tree *tree, const char *path)
 {
-        unsigned char hashy[GIT_MAX_RAWSZ];
+        struct object_id hashy;
         unsigned int mode_o;
 
-        return !get_tree_entry(tree->object.oid.hash, path,
-                               hashy, &mode_o);
+        return !get_tree_entry(&tree->object.oid, path,
+                               &hashy, &mode_o);
 }
 
 /*
@@ -2159,9 +2159,9 @@ static void apply_directory_rename_modifications(struct merge_options *o,
          * the various conflict_rename_*() functions update the index
          * explicitly rather than relying on unpack_trees() to have done it.
          */
-        get_tree_entry(tree->object.oid.hash,
+        get_tree_entry(&tree->object.oid,
                        pair->two->path,
-                       re->dst_entry->stages[stage].oid.hash,
+                       &re->dst_entry->stages[stage].oid,
                        &re->dst_entry->stages[stage].mode);
 
         /* Update pair status */
@@ -2646,7 +2646,7 @@ static int read_oid_strbuf(struct merge_options *o,
         void *buf;
         enum object_type type;
         unsigned long size;
-        buf = read_sha1_file(oid->hash, &type, &size);
+        buf = read_object_file(oid, &type, &size);
         if (!buf)
                 return err(o, _("cannot read object %s"), oid_to_hex(oid));
         if (type != OBJ_BLOB) {
diff --git a/notes-cache.c b/notes-cache.c
index 398e61d5e9..e61988e503 100644
--- a/notes-cache.c
+++ b/notes-cache.c
@@ -77,7 +77,7 @@ char *notes_cache_get(struct notes_cache *c, struct object_id *key_oid,
         value_oid = get_note(&c->tree, key_oid);
         if (!value_oid)
                 return NULL;
-        value = read_sha1_file(value_oid->hash, &type, &size);
+        value = read_object_file(value_oid, &type, &size);
 
         *outsize = size;
         return value;
diff --git a/notes-merge.c b/notes-merge.c
index c09c5e0e47..8e0726a941 100644
--- a/notes-merge.c
+++ b/notes-merge.c
@@ -322,7 +322,7 @@ static void write_note_to_worktree(const struct object_id *obj,
 {
         enum object_type type;
         unsigned long size;
-        void *buf = read_sha1_file(note->hash, &type, &size);
+        void *buf = read_object_file(note, &type, &size);
 
         if (!buf)
                 die("cannot read note %s for object %s",
diff --git a/notes.c b/notes.c
index ce9a8f53f8..a386d450c4 100644
--- a/notes.c
+++ b/notes.c
@@ -796,13 +796,13 @@ int combine_notes_concatenate(struct object_id *cur_oid,
 
         /* read in both note blob objects */
         if (!is_null_oid(new_oid))
-                new_msg = read_sha1_file(new_oid->hash, &new_type, &new_len);
+                new_msg = read_object_file(new_oid, &new_type, &new_len);
         if (!new_msg || !new_len || new_type != OBJ_BLOB) {
                 free(new_msg);
                 return 0;
         }
         if (!is_null_oid(cur_oid))
-                cur_msg = read_sha1_file(cur_oid->hash, &cur_type, &cur_len);
+                cur_msg = read_object_file(cur_oid, &cur_type, &cur_len);
         if (!cur_msg || !cur_len || cur_type != OBJ_BLOB) {
                 free(cur_msg);
                 free(new_msg);
@@ -858,7 +858,7 @@ static int string_list_add_note_lines(struct string_list *list,
                 return 0;
 
         /* read_sha1_file NUL-terminates */
-        data = read_sha1_file(oid->hash, &t, &len);
+        data = read_object_file(oid, &t, &len);
         if (t != OBJ_BLOB || !data || !len) {
                 free(data);
                 return t != OBJ_BLOB || !data;
@@ -1012,7 +1012,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
                 return;
         if (flags & NOTES_INIT_WRITABLE && read_ref(notes_ref, &object_oid))
                 die("Cannot use notes ref %s", notes_ref);
-        if (get_tree_entry(object_oid.hash, "", oid.hash, &mode))
+        if (get_tree_entry(&object_oid, "", &oid, &mode))
                 die("Failed to read notes tree referenced by %s (%s)",
                     notes_ref, oid_to_hex(&object_oid));
 
@@ -1217,7 +1217,7 @@ static void format_note(struct notes_tree *t, const struct object_id *object_oid
         if (!oid)
                 return;
 
-        if (!(msg = read_sha1_file(oid->hash, &type, &msglen)) || type != OBJ_BLOB) {
+        if (!(msg = read_object_file(oid, &type, &msglen)) || type != OBJ_BLOB) {
                 free(msg);
                 return;
         }
diff --git a/object.c b/object.c
index e6ad3f61f0..2c909385a7 100644
--- a/object.c
+++ b/object.c
@@ -244,7 +244,7 @@ struct object *parse_object(const struct object_id *oid)
         unsigned long size;
         enum object_type type;
         int eaten;
-        const unsigned char *repl = lookup_replace_object(oid->hash);
+        const struct object_id *repl = lookup_replace_object(oid);
         void *buffer;
         struct object *obj;
 
@@ -254,8 +254,8 @@ struct object *parse_object(const struct object_id *oid)
 
         if ((obj && obj->type == OBJ_BLOB && has_object_file(oid)) ||
             (!obj && has_object_file(oid) &&
-             sha1_object_info(oid->hash, NULL) == OBJ_BLOB)) {
-                if (check_sha1_signature(repl, NULL, 0, NULL) < 0) {
+             oid_object_info(oid, NULL) == OBJ_BLOB)) {
+                if (check_object_signature(repl, NULL, 0, NULL) < 0) {
                         error("sha1 mismatch %s", oid_to_hex(oid));
                         return NULL;
                 }
@@ -263,11 +263,11 @@ struct object *parse_object(const struct object_id *oid)
                 return lookup_object(oid->hash);
         }
 
-        buffer = read_sha1_file(oid->hash, &type, &size);
+        buffer = read_object_file(oid, &type, &size);
         if (buffer) {
-                if (check_sha1_signature(repl, buffer, size, type_name(type)) < 0) {
+                if (check_object_signature(repl, buffer, size, type_name(type)) < 0) {
                         free(buffer);
-                        error("sha1 mismatch %s", sha1_to_hex(repl));
+                        error("sha1 mismatch %s", oid_to_hex(repl));
                         return NULL;
                 }
 
diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c
index e01f992884..41ae27fb19 100644
--- a/pack-bitmap-write.c
+++ b/pack-bitmap-write.c
@@ -73,8 +73,7 @@ void bitmap_writer_build_type_index(struct pack_idx_entry **index,
                         break;
 
                 default:
-                        real_type = sha1_object_info(entry->idx.oid.hash,
-                                                     NULL);
+                        real_type = oid_object_info(&entry->idx.oid, NULL);
                         break;
                 }
 
diff --git a/pack-check.c b/pack-check.c
index 8fc7dd1694..d0591dd5e8 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -126,7 +126,7 @@ static int verify_packfile(struct packed_git *p,
 
                 if (type == OBJ_BLOB && big_file_threshold <= size) {
                         /*
-                         * Let check_sha1_signature() check it with
+                         * Let check_object_signature() check it with
                          * the streaming interface; no point slurping
                          * the data in-core only to discard.
                          */
@@ -141,7 +141,7 @@ static int verify_packfile(struct packed_git *p,
                         err = error("cannot unpack %s from %s at offset %"PRIuMAX"",
                                     oid_to_hex(entries[i].oid.oid), p->pack_name,
                                     (uintmax_t)entries[i].offset);
-                else if (check_sha1_signature(entries[i].oid.hash, data, size, type_name(type)))
+                else if (check_object_signature(entries[i].oid.oid, data, size, type_name(type)))
                         err = error("packed %s from %s is corrupt",
                                     oid_to_hex(entries[i].oid.oid), p->pack_name);
                 else if (fn) {
diff --git a/packfile.c b/packfile.c
index 7c1a2519fc..f26395ecab 100644
--- a/packfile.c
+++ b/packfile.c
@@ -1095,13 +1095,13 @@ static int retry_bad_packed_offset(struct packed_git *p, off_t obj_offset)
 {
         int type;
         struct revindex_entry *revidx;
-        const unsigned char *sha1;
+        struct object_id oid;
         revidx = find_pack_revindex(p, obj_offset);
         if (!revidx)
                 return OBJ_BAD;
-        sha1 = nth_packed_object_sha1(p, revidx->nr);
-        mark_bad_packed_object(p, sha1);
-        type = sha1_object_info(sha1, NULL);
+        nth_packed_object_oid(&oid, p, revidx->nr);
+        mark_bad_packed_object(p, oid.hash);
+        type = oid_object_info(&oid, NULL);
         if (type <= OBJ_NONE)
                 return OBJ_BAD;
         return type;
@@ -1452,7 +1452,7 @@ struct unpack_entry_stack_ent {
         unsigned long size;
 };
 
-static void *read_object(const unsigned char *sha1, enum object_type *type,
+static void *read_object(const struct object_id *oid, enum object_type *type,
                          unsigned long *size)
 {
         struct object_info oi = OBJECT_INFO_INIT;
@@ -1461,7 +1461,7 @@ static void *read_object(const unsigned char *sha1, enum object_type *type,
         oi.sizep = size;
         oi.contentp = &content;
 
-        if (sha1_object_info_extended(sha1, &oi, 0) < 0)
+        if (oid_object_info_extended(oid, &oi, 0) < 0)
                 return NULL;
         return content;
 }
@@ -1501,11 +1501,11 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
                         struct revindex_entry *revidx = find_pack_revindex(p, obj_offset);
                         off_t len = revidx[1].offset - obj_offset;
                         if (check_pack_crc(p, &w_curs, obj_offset, len, revidx->nr)) {
-                                const unsigned char *sha1 =
-                                        nth_packed_object_sha1(p, revidx->nr);
+                                struct object_id oid;
+                                nth_packed_object_oid(&oid, p, revidx->nr);
                                 error("bad packed object CRC for %s",
-                                      sha1_to_hex(sha1));
-                                mark_bad_packed_object(p, sha1);
+                                      oid_to_hex(&oid));
+                                mark_bad_packed_object(p, oid.hash);
                                 data = NULL;
                                 goto out;
                         }
@@ -1588,16 +1588,16 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
                          * of a corrupted pack, and is better than failing outright.
                          */
                         struct revindex_entry *revidx;
-                        const unsigned char *base_sha1;
+                        struct object_id base_oid;
                         revidx = find_pack_revindex(p, obj_offset);
                         if (revidx) {
-                                base_sha1 = nth_packed_object_sha1(p, revidx->nr);
+                                nth_packed_object_oid(&base_oid, p, revidx->nr);
                                 error("failed to read delta base object %s"
                                       " at offset %"PRIuMAX" from %s",
-                                      sha1_to_hex(base_sha1), (uintmax_t)obj_offset,
+                                      oid_to_hex(&base_oid), (uintmax_t)obj_offset,
                                       p->pack_name);
-                                mark_bad_packed_object(p, base_sha1);
-                                base = read_object(base_sha1, &type, &base_size);
+                                mark_bad_packed_object(p, base_oid.hash);
+                                base = read_object(&base_oid, &type, &base_size);
                                 external_base = base;
                         }
                 }
diff --git a/pretty.c b/pretty.c
index f7ce490230..34fe891fc0 100644
--- a/pretty.c
+++ b/pretty.c
@@ -549,7 +549,7 @@ static void add_merge_info(const struct pretty_print_context *pp,
                 struct object_id *oidp = &parent->item->object.oid;
                 strbuf_addch(sb, ' ');
                 if (pp->abbrev)
-                        strbuf_add_unique_abbrev(sb, oidp->hash, pp->abbrev);
+                        strbuf_add_unique_abbrev(sb, oidp, pp->abbrev);
                 else
                         strbuf_addstr(sb, oid_to_hex(oidp));
                 parent = parent->next;
@@ -1156,7 +1156,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                 return 1;
         case 'h':                /* abbreviated commit hash */
                 strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
-                strbuf_add_unique_abbrev(sb, commit->object.oid.hash,
+                strbuf_add_unique_abbrev(sb, &commit->object.oid,
                                          c->pretty_ctx->abbrev);
                 strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
                 return 1;
@@ -1164,7 +1164,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                 strbuf_addstr(sb, oid_to_hex(&commit->tree->object.oid));
                 return 1;
         case 't':                /* abbreviated tree hash */
-                strbuf_add_unique_abbrev(sb, commit->tree->object.oid.hash,
+                strbuf_add_unique_abbrev(sb, &commit->tree->object.oid,
                                          c->pretty_ctx->abbrev);
                 return 1;
         case 'P':                /* parent hashes */
@@ -1178,7 +1178,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                 for (p = commit->parents; p; p = p->next) {
                         if (p != commit->parents)
                                 strbuf_addch(sb, ' ');
-                        strbuf_add_unique_abbrev(sb, p->item->object.oid.hash,
+                        strbuf_add_unique_abbrev(sb, &p->item->object.oid,
                                                  c->pretty_ctx->abbrev);
                 }
                 return 1;
diff --git a/reachable.c b/reachable.c
index 191ebe3e6a..404e1440e9 100644
--- a/reachable.c
+++ b/reachable.c
@@ -77,7 +77,7 @@ static void add_recent_object(const struct object_id *oid,
          * later processing, and the revision machinery expects
          * commits and tags to have been parsed.
          */
-        type = sha1_object_info(oid->hash, NULL);
+        type = oid_object_info(oid, NULL);
         if (type < 0)
                 die("unable to get object info for %s", oid_to_hex(oid));
 
diff --git a/read-cache.c b/read-cache.c
index 59a73f4a81..10f1c6bb8a 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -185,7 +185,7 @@ static int ce_compare_link(const struct cache_entry *ce, size_t expected_size)
         if (strbuf_readlink(&sb, ce->name, expected_size))
                 return -1;
 
-        buffer = read_sha1_file(ce->oid.hash, &type, &size);
+        buffer = read_object_file(&ce->oid, &type, &size);
         if (buffer) {
                 if (size == sb.len)
                         match = memcmp(buffer, sb.buf, size);
@@ -2693,7 +2693,7 @@ void *read_blob_data_from_index(const struct index_state *istate,
         }
         if (pos < 0)
                 return NULL;
-        data = read_sha1_file(istate->cache[pos]->oid.hash, &type, &sz);
+        data = read_object_file(&istate->cache[pos]->oid, &type, &sz);
         if (!data || type != OBJ_BLOB) {
                 free(data);
                 return NULL;
diff --git a/ref-filter.c b/ref-filter.c
index 45fc56216a..9a333e21b5 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -728,7 +728,7 @@ int verify_ref_format(struct ref_format *format)
 static void *get_obj(const struct object_id *oid, struct object **obj, unsigned long *sz, int *eaten)
 {
         enum object_type type;
-        void *buf = read_sha1_file(oid->hash, &type, sz);
+        void *buf = read_object_file(oid, &type, sz);
 
         if (buf)
                 *obj = parse_object_buffer(oid, type, *sz, buf, eaten);
@@ -737,18 +737,18 @@ static void *get_obj(const struct object_id *oid, struct object **obj, unsigned
         return buf;
 }
 
-static int grab_objectname(const char *name, const unsigned char *sha1,
+static int grab_objectname(const char *name, const struct object_id *oid,
                            struct atom_value *v, struct used_atom *atom)
 {
         if (starts_with(name, "objectname")) {
                 if (atom->u.objectname.option == O_SHORT) {
-                        v->s = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV));
+                        v->s = xstrdup(find_unique_abbrev(oid, DEFAULT_ABBREV));
                         return 1;
                 } else if (atom->u.objectname.option == O_FULL) {
-                        v->s = xstrdup(sha1_to_hex(sha1));
+                        v->s = xstrdup(oid_to_hex(oid));
                         return 1;
                 } else if (atom->u.objectname.option == O_LENGTH) {
-                        v->s = xstrdup(find_unique_abbrev(sha1, atom->u.objectname.length));
+                        v->s = xstrdup(find_unique_abbrev(oid, atom->u.objectname.length));
                         return 1;
                 } else
                         die("BUG: unknown %%(objectname) option");
@@ -775,7 +775,7 @@ static void grab_common_values(struct atom_value *val, int deref, struct object
                         v->s = xstrfmt("%lu", sz);
                 }
                 else if (deref)
-                        grab_objectname(name, obj->oid.hash, v, &used_atom[i]);
+                        grab_objectname(name, &obj->oid, v, &used_atom[i]);
         }
 }
 
@@ -1455,7 +1455,7 @@ static void populate_value(struct ref_array_item *ref)
                                 v->s = xstrdup(buf + 1);
                         }
                         continue;
-                } else if (!deref && grab_objectname(name, ref->objectname.hash, v, atom)) {
+                } else if (!deref && grab_objectname(name, &ref->objectname, v, atom)) {
                         continue;
                 } else if (!strcmp(name, "HEAD")) {
                         if (atom->u.head && !strcmp(ref->refname, atom->u.head))
diff --git a/refs.c b/refs.c
index 20ba82b434..8b7a77fe5e 100644
--- a/refs.c
+++ b/refs.c
@@ -301,7 +301,7 @@ enum peel_status peel_object(const struct object_id *name, struct object_id *oid
         struct object *o = lookup_unknown_object(name->hash);
 
         if (o->type == OBJ_NONE) {
-                int type = sha1_object_info(name->hash, NULL);
+                int type = oid_object_info(name, NULL);
                 if (type < 0 || !object_as_type(o, type, 0))
                         return PEEL_INVALID;
         }
diff --git a/remote-testsvn.c b/remote-testsvn.c
index bcebb4c789..c4bb9a8ba9 100644
--- a/remote-testsvn.c
+++ b/remote-testsvn.c
@@ -61,7 +61,7 @@ static char *read_ref_note(const struct object_id *oid)
         init_notes(NULL, notes_ref, NULL, 0);
         if (!(note_oid = get_note(NULL, oid)))
                 return NULL;        /* note tree not found */
-        if (!(msg = read_sha1_file(note_oid->hash, &type, &msglen)))
+        if (!(msg = read_object_file(note_oid, &type, &msglen)))
                 error("Empty notes tree. %s", notes_ref);
         else if (!msglen || type != OBJ_BLOB) {
                 error("Note contains unusable content. "
@@ -108,7 +108,7 @@ static int note2mark_cb(const struct object_id *object_oid,
         enum object_type type;
         struct rev_note note;
 
-        if (!(msg = read_sha1_file(note_oid->hash, &type, &msglen)) ||
+        if (!(msg = read_object_file(note_oid, &type, &msglen)) ||
                         !msglen || type != OBJ_BLOB) {
                 free(msg);
                 return 1;
diff --git a/remote.c b/remote.c
index c10d87c246..91eb010ca9 100644
--- a/remote.c
+++ b/remote.c
@@ -1376,7 +1376,7 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds
                         continue; /* not a tag */
                 if (string_list_has_string(&dst_tag, ref->name))
                         continue; /* they already have it */
-                if (sha1_object_info(ref->new_oid.hash, NULL) != OBJ_TAG)
+                if (oid_object_info(&ref->new_oid, NULL) != OBJ_TAG)
                         continue; /* be conservative */
                 item = string_list_append(&src_tag, ref->name);
                 item->util = ref;
diff --git a/replace_object.c b/replace_object.c
index 3e49965d05..336357394d 100644
--- a/replace_object.c
+++ b/replace_object.c
@@ -8,8 +8,8 @@
  * sha1.
  */
 static struct replace_object {
-        unsigned char original[20];
-        unsigned char replacement[20];
+        struct object_id original;
+        struct object_id replacement;
 } **replace_object;
 
 static int replace_object_alloc, replace_object_nr;
@@ -17,7 +17,7 @@ static int replace_object_alloc, replace_object_nr;
 static const unsigned char *replace_sha1_access(size_t index, void *table)
 {
         struct replace_object **replace = table;
-        return replace[index]->original;
+        return replace[index]->original.hash;
 }
 
 static int replace_object_pos(const unsigned char *sha1)
@@ -29,7 +29,7 @@ static int replace_object_pos(const unsigned char *sha1)
 static int register_replace_object(struct replace_object *replace,
                                    int ignore_dups)
 {
-        int pos = replace_object_pos(replace->original);
+        int pos = replace_object_pos(replace->original.hash);
 
         if (0 <= pos) {
                 if (ignore_dups)
@@ -59,14 +59,14 @@ static int register_replace_ref(const char *refname,
         const char *hash = slash ? slash + 1 : refname;
         struct replace_object *repl_obj = xmalloc(sizeof(*repl_obj));
 
-        if (strlen(hash) != 40 || get_sha1_hex(hash, repl_obj->original)) {
+        if (get_oid_hex(hash, &repl_obj->original)) {
                 free(repl_obj);
                 warning("bad replace ref name: %s", refname);
                 return 0;
         }
 
         /* Copy sha1 from the read ref */
-        hashcpy(repl_obj->replacement, oid->hash);
+        oidcpy(&repl_obj->replacement, oid);
 
         /* Register new object */
         if (register_replace_object(repl_obj, 1))
@@ -92,16 +92,16 @@ static void prepare_replace_object(void)
 #define MAXREPLACEDEPTH 5
 
 /*
- * If a replacement for object sha1 has been set up, return the
+ * If a replacement for object oid has been set up, return the
  * replacement object's name (replaced recursively, if necessary).
- * The return value is either sha1 or a pointer to a
+ * The return value is either oid or a pointer to a
  * permanently-allocated value.  This function always respects replace
  * references, regardless of the value of check_replace_refs.
  */
-const unsigned char *do_lookup_replace_object(const unsigned char *sha1)
+const struct object_id *do_lookup_replace_object(const struct object_id *oid)
 {
         int pos, depth = MAXREPLACEDEPTH;
-        const unsigned char *cur = sha1;
+        const struct object_id *cur = oid;
 
         prepare_replace_object();
 
@@ -109,11 +109,11 @@ const unsigned char *do_lookup_replace_object(const unsigned char *sha1)
         do {
                 if (--depth < 0)
                         die("replace depth too high for object %s",
-                            sha1_to_hex(sha1));
+                            oid_to_hex(oid));
 
-                pos = replace_object_pos(cur);
+                pos = replace_object_pos(cur->hash);
                 if (0 <= pos)
-                        cur = replace_object[pos]->replacement;
+                        cur = &replace_object[pos]->replacement;
         } while (0 <= pos);
 
         return cur;
diff --git a/rerere.c b/rerere.c
index ea24d4c2f4..18cae2d11c 100644
--- a/rerere.c
+++ b/rerere.c
@@ -979,8 +979,8 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu
                         break;
                 i = ce_stage(ce) - 1;
                 if (!mmfile[i].ptr) {
-                        mmfile[i].ptr = read_sha1_file(ce->oid.hash, &type,
-                                                       &size);
+                        mmfile[i].ptr = read_object_file(&ce->oid, &type,
+                                                         &size);
                         mmfile[i].size = size;
                 }
         }
diff --git a/resolve-undo.c b/resolve-undo.c
index b40f3173d3..aed95b4b35 100644
--- a/resolve-undo.c
+++ b/resolve-undo.c
@@ -24,7 +24,7 @@ void record_resolve_undo(struct index_state *istate, struct cache_entry *ce)
         if (!lost->util)
                 lost->util = xcalloc(1, sizeof(*ui));
         ui = lost->util;
-        hashcpy(ui->sha1[stage - 1], ce->oid.hash);
+        oidcpy(&ui->oid[stage - 1], &ce->oid);
         ui->mode[stage - 1] = ce->ce_mode;
 }
 
@@ -44,7 +44,7 @@ void resolve_undo_write(struct strbuf *sb, struct string_list *resolve_undo)
                 for (i = 0; i < 3; i++) {
                         if (!ui->mode[i])
                                 continue;
-                        strbuf_add(sb, ui->sha1[i], 20);
+                        strbuf_add(sb, ui->oid[i].hash, the_hash_algo->rawsz);
                 }
         }
 }
@@ -55,6 +55,7 @@ struct string_list *resolve_undo_read(const char *data, unsigned long size)
         size_t len;
         char *endptr;
         int i;
+        const unsigned rawsz = the_hash_algo->rawsz;
 
         resolve_undo = xcalloc(1, sizeof(*resolve_undo));
         resolve_undo->strdup_strings = 1;
@@ -87,11 +88,11 @@ struct string_list *resolve_undo_read(const char *data, unsigned long size)
                 for (i = 0; i < 3; i++) {
                         if (!ui->mode[i])
                                 continue;
-                        if (size < 20)
+                        if (size < rawsz)
                                 goto error;
-                        hashcpy(ui->sha1[i], (const unsigned char *)data);
-                        size -= 20;
-                        data += 20;
+                        memcpy(ui->oid[i].hash, (const unsigned char *)data, rawsz);
+                        size -= rawsz;
+                        data += rawsz;
                 }
         }
         return resolve_undo;
@@ -145,7 +146,7 @@ int unmerge_index_entry_at(struct index_state *istate, int pos)
                 struct cache_entry *nce;
                 if (!ru->mode[i])
                         continue;
-                nce = make_cache_entry(ru->mode[i], ru->sha1[i],
+                nce = make_cache_entry(ru->mode[i], ru->oid[i].hash,
                                        name, i + 1, 0);
                 if (matched)
                         nce->ce_flags |= CE_MATCHED;
diff --git a/resolve-undo.h b/resolve-undo.h
index 46306455ed..87291904bd 100644
--- a/resolve-undo.h
+++ b/resolve-undo.h
@@ -3,7 +3,7 @@
 
 struct resolve_undo_info {
         unsigned int mode[3];
-        unsigned char sha1[3][20];
+        struct object_id oid[3];
 };
 
 extern void record_resolve_undo(struct index_state *, struct cache_entry *);
diff --git a/send-pack.c b/send-pack.c
index 8d9190f5e7..19025a7aca 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -37,14 +37,14 @@ int option_parse_push_signed(const struct option *opt,
         die("bad %s argument: %s", opt->long_name, arg);
 }
 
-static void feed_object(const unsigned char *sha1, FILE *fh, int negative)
+static void feed_object(const struct object_id *oid, FILE *fh, int negative)
 {
-        if (negative && !has_sha1_file(sha1))
+        if (negative && !has_sha1_file(oid->hash))
                 return;
 
         if (negative)
                 putc('^', fh);
-        fputs(sha1_to_hex(sha1), fh);
+        fputs(oid_to_hex(oid), fh);
         putc('\n', fh);
 }
 
@@ -89,13 +89,13 @@ static int pack_objects(int fd, struct ref *refs, struct oid_array *extra, struc
          */
         po_in = xfdopen(po.in, "w");
         for (i = 0; i < extra->nr; i++)
-                feed_object(extra->oid[i].hash, po_in, 1);
+                feed_object(&extra->oid[i], po_in, 1);
 
         while (refs) {
                 if (!is_null_oid(&refs->old_oid))
-                        feed_object(refs->old_oid.hash, po_in, 1);
+                        feed_object(&refs->old_oid, po_in, 1);
                 if (!is_null_oid(&refs->new_oid))
-                        feed_object(refs->new_oid.hash, po_in, 0);
+                        feed_object(&refs->new_oid, po_in, 0);
                 refs = refs->next;
         }
 
diff --git a/sequencer.c b/sequencer.c
index f9d1001dee..667f35ebdf 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -282,7 +282,7 @@ struct commit_message {
 
 static const char *short_commit_name(struct commit *commit)
 {
-        return find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV);
+        return find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV);
 }
 
 static int get_message(struct commit *commit, struct commit_message *out)
@@ -1112,7 +1112,7 @@ static int try_to_commit(struct strbuf *msg, const char *author,
                 commit_list_insert(current_head, &parents);
         }
 
-        if (write_cache_as_tree(tree.hash, 0, NULL)) {
+        if (write_cache_as_tree(&tree, 0, NULL)) {
                 res = error(_("git write-tree failed to write a tree"));
                 goto out;
         }
@@ -1474,7 +1474,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                  * that represents the "current" state for merge-recursive
                  * to work on.
                  */
-                if (write_cache_as_tree(head.hash, 0, NULL))
+                if (write_cache_as_tree(&head, 0, NULL))
                         return error(_("your index file is unmerged."));
         } else {
                 unborn = get_oid("HEAD", &head);
@@ -2876,7 +2876,8 @@ int sequencer_pick_revisions(struct replay_opts *opts)
 
                 if (!get_oid(name, &oid)) {
                         if (!lookup_commit_reference_gently(&oid, 1)) {
-                                enum object_type type = sha1_object_info(oid.hash, NULL);
+                                enum object_type type = oid_object_info(&oid,
+                                                                        NULL);
                                 return error(_("%s: can't cherry-pick a %s"),
                                         name, type_name(type));
                         }
diff --git a/sha1_file.c b/sha1_file.c
index ad77549565..1c61d9d927 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -30,6 +30,9 @@
 #include "packfile.h"
 #include "fetch-object.h"
 
+/* The maximum size for an object header. */
+#define MAX_HEADER_LEN 32
+
 const unsigned char null_sha1[GIT_MAX_RAWSZ];
 const struct object_id null_oid;
 const struct object_id empty_tree_oid = {
@@ -784,22 +787,22 @@ void *xmmap(void *start, size_t length,
  * With "map" == NULL, try reading the object named with "sha1" using
  * the streaming interface and rehash it to do the same.
  */
-int check_sha1_signature(const unsigned char *sha1, void *map,
-                         unsigned long size, const char *type)
+int check_object_signature(const struct object_id *oid, void *map,
+                           unsigned long size, const char *type)
 {
         struct object_id real_oid;
         enum object_type obj_type;
         struct git_istream *st;
         git_hash_ctx c;
-        char hdr[32];
+        char hdr[MAX_HEADER_LEN];
         int hdrlen;
 
         if (map) {
                 hash_object_file(map, size, type, &real_oid);
-                return hashcmp(sha1, real_oid.hash) ? -1 : 0;
+                return oidcmp(oid, &real_oid) ? -1 : 0;
         }
 
-        st = open_istream(sha1, &obj_type, &size, NULL);
+        st = open_istream(oid, &obj_type, &size, NULL);
         if (!st)
                 return -1;
 
@@ -823,7 +826,7 @@ int check_sha1_signature(const unsigned char *sha1, void *map,
         }
         the_hash_algo->final_fn(real_oid.hash, &c);
         close_istream(st);
-        return hashcmp(sha1, real_oid.hash) ? -1 : 0;
+        return oidcmp(oid, &real_oid) ? -1 : 0;
 }
 
 int git_open_cloexec(const char *name, int flags)
@@ -1150,7 +1153,7 @@ static int sha1_loose_object_info(const unsigned char *sha1,
         unsigned long mapsize;
         void *map;
         git_zstream stream;
-        char hdr[32];
+        char hdr[MAX_HEADER_LEN];
         struct strbuf hdrbuf = STRBUF_INIT;
         unsigned long size_scratch;
 
@@ -1222,24 +1225,25 @@ static int sha1_loose_object_info(const unsigned char *sha1,
 
 int fetch_if_missing = 1;
 
-int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, unsigned flags)
+int oid_object_info_extended(const struct object_id *oid, struct object_info *oi, unsigned flags)
 {
         static struct object_info blank_oi = OBJECT_INFO_INIT;
         struct pack_entry e;
         int rtype;
-        const unsigned char *real = (flags & OBJECT_INFO_LOOKUP_REPLACE) ?
-                                    lookup_replace_object(sha1) :
-                                    sha1;
+        const struct object_id *real = oid;
         int already_retried = 0;
 
-        if (is_null_sha1(real))
+        if (flags & OBJECT_INFO_LOOKUP_REPLACE)
+                real = lookup_replace_object(oid);
+
+        if (is_null_oid(real))
                 return -1;
 
         if (!oi)
                 oi = &blank_oi;
 
         if (!(flags & OBJECT_INFO_SKIP_CACHED)) {
-                struct cached_object *co = find_cached_object(real);
+                struct cached_object *co = find_cached_object(real->hash);
                 if (co) {
                         if (oi->typep)
                                 *(oi->typep) = co->type;
@@ -1259,20 +1263,20 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
         }
 
         while (1) {
-                if (find_pack_entry(real, &e))
+                if (find_pack_entry(real->hash, &e))
                         break;
 
                 if (flags & OBJECT_INFO_IGNORE_LOOSE)
                         return -1;
 
                 /* Most likely it's a loose object. */
-                if (!sha1_loose_object_info(real, oi, flags))
+                if (!sha1_loose_object_info(real->hash, oi, flags))
                         return 0;
 
                 /* Not a loose object; someone else may have just packed it. */
                 if (!(flags & OBJECT_INFO_QUICK)) {
                         reprepare_packed_git();
-                        if (find_pack_entry(real, &e))
+                        if (find_pack_entry(real->hash, &e))
                                 break;
                 }
 
@@ -1283,7 +1287,7 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
                          * TODO Investigate haveing fetch_object() return
                          * TODO error/success and stopping the music here.
                          */
-                        fetch_object(repository_format_partial_clone, real);
+                        fetch_object(repository_format_partial_clone, real->hash);
                         already_retried = 1;
                         continue;
                 }
@@ -1299,8 +1303,8 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
                 return 0;
         rtype = packed_object_info(e.p, e.offset, oi);
         if (rtype < 0) {
-                mark_bad_packed_object(e.p, real);
-                return sha1_object_info_extended(real, oi, 0);
+                mark_bad_packed_object(e.p, real->hash);
+                return oid_object_info_extended(real, oi, 0);
         } else if (oi->whence == OI_PACKED) {
                 oi->u.packed.offset = e.offset;
                 oi->u.packed.pack = e.p;
@@ -1312,15 +1316,15 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
 }
 
 /* returns enum object_type or negative */
-int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
+int oid_object_info(const struct object_id *oid, unsigned long *sizep)
 {
         enum object_type type;
         struct object_info oi = OBJECT_INFO_INIT;
 
         oi.typep = &type;
         oi.sizep = sizep;
-        if (sha1_object_info_extended(sha1, &oi,
-                                      OBJECT_INFO_LOOKUP_REPLACE) < 0)
+        if (oid_object_info_extended(oid, &oi,
+                                     OBJECT_INFO_LOOKUP_REPLACE) < 0)
                 return -1;
         return type;
 }
@@ -1328,13 +1332,16 @@ int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
 static void *read_object(const unsigned char *sha1, enum object_type *type,
                          unsigned long *size)
 {
+        struct object_id oid;
         struct object_info oi = OBJECT_INFO_INIT;
         void *content;
         oi.typep = type;
         oi.sizep = size;
         oi.contentp = &content;
 
-        if (sha1_object_info_extended(sha1, &oi, 0) < 0)
+        hashcpy(oid.hash, sha1);
+
+        if (oid_object_info_extended(&oid, &oi, 0) < 0)
                 return NULL;
         return content;
 }
@@ -1362,65 +1369,65 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type,
  * deal with them should arrange to call read_object() and give error
  * messages themselves.
  */
-void *read_sha1_file_extended(const unsigned char *sha1,
-                              enum object_type *type,
-                              unsigned long *size,
-                              int lookup_replace)
+void *read_object_file_extended(const struct object_id *oid,
+                                enum object_type *type,
+                                unsigned long *size,
+                                int lookup_replace)
 {
         void *data;
         const struct packed_git *p;
         const char *path;
         struct stat st;
-        const unsigned char *repl = lookup_replace ? lookup_replace_object(sha1)
-                                                   : sha1;
+        const struct object_id *repl = lookup_replace ? lookup_replace_object(oid)
+                                                      : oid;
 
         errno = 0;
-        data = read_object(repl, type, size);
+        data = read_object(repl->hash, type, size);
         if (data)
                 return data;
 
         if (errno && errno != ENOENT)
-                die_errno("failed to read object %s", sha1_to_hex(sha1));
+                die_errno("failed to read object %s", oid_to_hex(oid));
 
         /* die if we replaced an object with one that does not exist */
-        if (repl != sha1)
+        if (repl != oid)
                 die("replacement %s not found for %s",
-                    sha1_to_hex(repl), sha1_to_hex(sha1));
+                    oid_to_hex(repl), oid_to_hex(oid));
 
-        if (!stat_sha1_file(repl, &st, &path))
+        if (!stat_sha1_file(repl->hash, &st, &path))
                 die("loose object %s (stored in %s) is corrupt",
-                    sha1_to_hex(repl), path);
+                    oid_to_hex(repl), path);
 
-        if ((p = has_packed_and_bad(repl)) != NULL)
+        if ((p = has_packed_and_bad(repl->hash)) != NULL)
                 die("packed object %s (stored in %s) is corrupt",
-                    sha1_to_hex(repl), p->pack_name);
+                    oid_to_hex(repl), p->pack_name);
 
         return NULL;
 }
 
-void *read_object_with_reference(const unsigned char *sha1,
+void *read_object_with_reference(const struct object_id *oid,
                                  const char *required_type_name,
                                  unsigned long *size,
-                                 unsigned char *actual_sha1_return)
+                                 struct object_id *actual_oid_return)
 {
         enum object_type type, required_type;
         void *buffer;
         unsigned long isize;
-        unsigned char actual_sha1[20];
+        struct object_id actual_oid;
 
         required_type = type_from_string(required_type_name);
-        hashcpy(actual_sha1, sha1);
+        oidcpy(&actual_oid, oid);
         while (1) {
                 int ref_length = -1;
                 const char *ref_type = NULL;
 
-                buffer = read_sha1_file(actual_sha1, &type, &isize);
+                buffer = read_object_file(&actual_oid, &type, &isize);
                 if (!buffer)
                         return NULL;
                 if (type == required_type) {
                         *size = isize;
-                        if (actual_sha1_return)
-                                hashcpy(actual_sha1_return, actual_sha1);
+                        if (actual_oid_return)
+                                oidcpy(actual_oid_return, &actual_oid);
                         return buffer;
                 }
                 /* Handle references */
@@ -1434,15 +1441,15 @@ void *read_object_with_reference(const unsigned char *sha1,
                 }
                 ref_length = strlen(ref_type);
 
-                if (ref_length + 40 > isize ||
+                if (ref_length + GIT_SHA1_HEXSZ > isize ||
                     memcmp(buffer, ref_type, ref_length) ||
-                    get_sha1_hex((char *) buffer + ref_length, actual_sha1)) {
+                    get_oid_hex((char *) buffer + ref_length, &actual_oid)) {
                         free(buffer);
                         return NULL;
                 }
                 free(buffer);
                 /* Now we have the ID of the referred-to object in
-                 * actual_sha1.  Check again. */
+                 * actual_oid.  Check again. */
         }
 }
 
@@ -1515,7 +1522,7 @@ static int write_buffer(int fd, const void *buf, size_t len)
 int hash_object_file(const void *buf, unsigned long len, const char *type,
                      struct object_id *oid)
 {
-        char hdr[32];
+        char hdr[MAX_HEADER_LEN];
         int hdrlen = sizeof(hdr);
         write_object_file_prepare(buf, len, type, oid, hdr, &hdrlen);
         return 0;
@@ -1670,7 +1677,7 @@ static int freshen_packed_object(const unsigned char *sha1)
 int write_object_file(const void *buf, unsigned long len, const char *type,
                       struct object_id *oid)
 {
-        char hdr[32];
+        char hdr[MAX_HEADER_LEN];
         int hdrlen = sizeof(hdr);
 
         /* Normally if we have it in the pack then we do not bother writing
@@ -1690,7 +1697,7 @@ int hash_object_file_literally(const void *buf, unsigned long len,
         int hdrlen, status = 0;
 
         /* type string, SP, %lu of the length plus NUL must fit this */
-        hdrlen = strlen(type) + 32;
+        hdrlen = strlen(type) + MAX_HEADER_LEN;
         header = xmalloc(hdrlen);
         write_object_file_prepare(buf, len, type, oid, header, &hdrlen);
 
@@ -1710,7 +1717,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime)
         void *buf;
         unsigned long len;
         enum object_type type;
-        char hdr[32];
+        char hdr[MAX_HEADER_LEN];
         int hdrlen;
         int ret;
 
@@ -1728,10 +1735,12 @@ int force_object_loose(const struct object_id *oid, time_t mtime)
 
 int has_sha1_file_with_flags(const unsigned char *sha1, int flags)
 {
+        struct object_id oid;
         if (!startup_info->have_repository)
                 return 0;
-        return sha1_object_info_extended(sha1, NULL,
-                                         flags | OBJECT_INFO_SKIP_CACHED) >= 0;
+        hashcpy(oid.hash, sha1);
+        return oid_object_info_extended(&oid, NULL,
+                                        flags | OBJECT_INFO_SKIP_CACHED) >= 0;
 }
 
 int has_object_file(const struct object_id *oid)
@@ -1897,7 +1906,7 @@ static int index_stream(struct object_id *oid, int fd, size_t size,
                         enum object_type type, const char *path,
                         unsigned flags)
 {
-        return index_bulk_checkin(oid->hash, fd, size, type, path, flags);
+        return index_bulk_checkin(oid, fd, size, type, path, flags);
 }
 
 int index_fd(struct object_id *oid, int fd, struct stat *st,
@@ -1971,13 +1980,13 @@ int read_pack_header(int fd, struct pack_header *header)
         return 0;
 }
 
-void assert_sha1_type(const unsigned char *sha1, enum object_type expect)
+void assert_oid_type(const struct object_id *oid, enum object_type expect)
 {
-        enum object_type type = sha1_object_info(sha1, NULL);
+        enum object_type type = oid_object_info(oid, NULL);
         if (type < 0)
-                die("%s is not a valid object", sha1_to_hex(sha1));
+                die("%s is not a valid object", oid_to_hex(oid));
         if (type != expect)
-                die("%s is not a valid '%s' object", sha1_to_hex(sha1),
+                die("%s is not a valid '%s' object", oid_to_hex(oid),
                     type_name(expect));
 }
 
@@ -2181,7 +2190,7 @@ static int check_stream_sha1(git_zstream *stream,
 }
 
 int read_loose_object(const char *path,
-                      const unsigned char *expected_sha1,
+                      const struct object_id *expected_oid,
                       enum object_type *type,
                       unsigned long *size,
                       void **contents)
@@ -2190,7 +2199,7 @@ int read_loose_object(const char *path,
         void *map = NULL;
         unsigned long mapsize;
         git_zstream stream;
-        char hdr[32];
+        char hdr[MAX_HEADER_LEN];
 
         *contents = NULL;
 
@@ -2213,19 +2222,19 @@ int read_loose_object(const char *path,
         }
 
         if (*type == OBJ_BLOB) {
-                if (check_stream_sha1(&stream, hdr, *size, path, expected_sha1) < 0)
+                if (check_stream_sha1(&stream, hdr, *size, path, expected_oid->hash) < 0)
                         goto out;
         } else {
-                *contents = unpack_sha1_rest(&stream, hdr, *size, expected_sha1);
+                *contents = unpack_sha1_rest(&stream, hdr, *size, expected_oid->hash);
                 if (!*contents) {
                         error("unable to unpack contents of %s", path);
                         git_inflate_end(&stream);
                         goto out;
                 }
-                if (check_sha1_signature(expected_sha1, *contents,
+                if (check_object_signature(expected_oid, *contents,
                                          *size, type_name(*type))) {
                         error("sha1 mismatch for %s (expected %s)", path,
-                              sha1_to_hex(expected_sha1));
+                              oid_to_hex(expected_oid));
                         free(*contents);
                         goto out;
                 }
diff --git a/sha1_name.c b/sha1_name.c
index 735c1c0b8e..39e911c8ba 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -238,7 +238,7 @@ static int finish_object_disambiguation(struct disambiguate_state *ds,
 
 static int disambiguate_commit_only(const struct object_id *oid, void *cb_data_unused)
 {
-        int kind = sha1_object_info(oid->hash, NULL);
+        int kind = oid_object_info(oid, NULL);
         return kind == OBJ_COMMIT;
 }
 
@@ -247,7 +247,7 @@ static int disambiguate_committish_only(const struct object_id *oid, void *cb_da
         struct object *obj;
         int kind;
 
-        kind = sha1_object_info(oid->hash, NULL);
+        kind = oid_object_info(oid, NULL);
         if (kind == OBJ_COMMIT)
                 return 1;
         if (kind != OBJ_TAG)
@@ -262,7 +262,7 @@ static int disambiguate_committish_only(const struct object_id *oid, void *cb_da
 
 static int disambiguate_tree_only(const struct object_id *oid, void *cb_data_unused)
 {
-        int kind = sha1_object_info(oid->hash, NULL);
+        int kind = oid_object_info(oid, NULL);
         return kind == OBJ_TREE;
 }
 
@@ -271,7 +271,7 @@ static int disambiguate_treeish_only(const struct object_id *oid, void *cb_data_
         struct object *obj;
         int kind;
 
-        kind = sha1_object_info(oid->hash, NULL);
+        kind = oid_object_info(oid, NULL);
         if (kind == OBJ_TREE || kind == OBJ_COMMIT)
                 return 1;
         if (kind != OBJ_TAG)
@@ -286,7 +286,7 @@ static int disambiguate_treeish_only(const struct object_id *oid, void *cb_data_
 
 static int disambiguate_blob_only(const struct object_id *oid, void *cb_data_unused)
 {
-        int kind = sha1_object_info(oid->hash, NULL);
+        int kind = oid_object_info(oid, NULL);
         return kind == OBJ_BLOB;
 }
 
@@ -365,7 +365,7 @@ static int show_ambiguous_object(const struct object_id *oid, void *data)
         if (ds->fn && !ds->fn(oid, ds->cb_data))
                 return 0;
 
-        type = sha1_object_info(oid->hash, NULL);
+        type = oid_object_info(oid, NULL);
         if (type == OBJ_COMMIT) {
                 struct commit *commit = lookup_commit(oid);
                 if (commit) {
@@ -380,7 +380,7 @@ static int show_ambiguous_object(const struct object_id *oid, void *data)
         }
 
         advise("  %s %s%s",
-               find_unique_abbrev(oid->hash, DEFAULT_ABBREV),
+               find_unique_abbrev(oid, DEFAULT_ABBREV),
                type_name(type) ? type_name(type) : "unknown type",
                desc.buf);
 
@@ -569,7 +569,7 @@ static void find_abbrev_len_packed(struct min_abbrev_data *mad)
                 find_abbrev_len_for_pack(p, mad);
 }
 
-int find_unique_abbrev_r(char *hex, const unsigned char *sha1, int len)
+int find_unique_abbrev_r(char *hex, const struct object_id *oid, int len)
 {
         struct disambiguate_state ds;
         struct min_abbrev_data mad;
@@ -596,14 +596,14 @@ int find_unique_abbrev_r(char *hex, const unsigned char *sha1, int len)
                         len = FALLBACK_DEFAULT_ABBREV;
         }
 
-        sha1_to_hex_r(hex, sha1);
+        oid_to_hex_r(hex, oid);
         if (len == GIT_SHA1_HEXSZ || !len)
                 return GIT_SHA1_HEXSZ;
 
         mad.init_len = len;
         mad.cur_len = len;
         mad.hex = hex;
-        mad.hash = sha1;
+        mad.hash = oid->hash;
 
         find_abbrev_len_packed(&mad);
 
@@ -621,13 +621,13 @@ int find_unique_abbrev_r(char *hex, const unsigned char *sha1, int len)
         return mad.cur_len;
 }
 
-const char *find_unique_abbrev(const unsigned char *sha1, int len)
+const char *find_unique_abbrev(const struct object_id *oid, int len)
 {
         static int bufno;
         static char hexbuffer[4][GIT_MAX_HEXSZ + 1];
         char *hex = hexbuffer[bufno];
         bufno = (bufno + 1) % ARRAY_SIZE(hexbuffer);
-        find_unique_abbrev_r(hex, sha1, len);
+        find_unique_abbrev_r(hex, oid, len);
         return hex;
 }
 
@@ -1529,8 +1529,7 @@ static void diagnose_invalid_oid_path(const char *prefix,
         if (is_missing_file_error(errno)) {
                 char *fullname = xstrfmt("%s%s", prefix, filename);
 
-                if (!get_tree_entry(tree_oid->hash, fullname,
-                                    oid.hash, &mode)) {
+                if (!get_tree_entry(tree_oid, fullname, &oid, &mode)) {
                         die("Path '%s' exists, but not '%s'.\n"
                             "Did you mean '%.*s:%s' aka '%.*s:./%s'?",
                             fullname,
@@ -1722,8 +1721,8 @@ static int get_oid_with_context_1(const char *name,
                                         filename, oid->hash, &oc->symlink_path,
                                         &oc->mode);
                         } else {
-                                ret = get_tree_entry(tree_oid.hash, filename,
-                                                     oid->hash, &oc->mode);
+                                ret = get_tree_entry(&tree_oid, filename, oid,
+                                                     &oc->mode);
                                 if (ret && only_to_die) {
                                         diagnose_invalid_oid_path(prefix,
                                                                    filename,
diff --git a/strbuf.c b/strbuf.c
index 013fc673fa..83d05024e6 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -897,12 +897,12 @@ void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm,
         strbuf_setlen(sb, sb->len + len);
 }
 
-void strbuf_add_unique_abbrev(struct strbuf *sb, const unsigned char *sha1,
+void strbuf_add_unique_abbrev(struct strbuf *sb, const struct object_id *oid,
                               int abbrev_len)
 {
         int r;
         strbuf_grow(sb, GIT_SHA1_HEXSZ + 1);
-        r = find_unique_abbrev_r(sb->buf + sb->len, sha1, abbrev_len);
+        r = find_unique_abbrev_r(sb->buf + sb->len, oid, abbrev_len);
         strbuf_setlen(sb, sb->len + r);
 }
 
diff --git a/strbuf.h b/strbuf.h
index 652f17392c..c4de5e4588 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -72,6 +72,12 @@ struct strbuf {
 extern char strbuf_slopbuf[];
 #define STRBUF_INIT  { .alloc = 0, .len = 0, .buf = strbuf_slopbuf }
 
+/*
+ * Predeclare this here, since cache.h includes this file before it defines the
+ * struct.
+ */
+struct object_id;
+
 /**
  * Life Cycle Functions
  * --------------------
@@ -558,7 +564,7 @@ extern void strbuf_list_free(struct strbuf **);
  * the strbuf `sb`.
  */
 extern void strbuf_add_unique_abbrev(struct strbuf *sb,
-                                     const unsigned char *sha1,
+                                     const struct object_id *oid,
                                      int abbrev_len);
 
 /**
diff --git a/streaming.c b/streaming.c
index 5892b50bd8..46fabee3aa 100644
--- a/streaming.c
+++ b/streaming.c
@@ -14,7 +14,7 @@ enum input_source {
 
 typedef int (*open_istream_fn)(struct git_istream *,
                                struct object_info *,
-                               const unsigned char *,
+                               const struct object_id *,
                                enum object_type *);
 typedef int (*close_istream_fn)(struct git_istream *);
 typedef ssize_t (*read_istream_fn)(struct git_istream *, char *, size_t);
@@ -27,7 +27,7 @@ struct stream_vtbl {
 #define open_method_decl(name) \
         int open_istream_ ##name \
         (struct git_istream *st, struct object_info *oi, \
-         const unsigned char *sha1, \
+         const struct object_id *oid, \
          enum object_type *type)
 
 #define close_method_decl(name) \
@@ -105,7 +105,7 @@ ssize_t read_istream(struct git_istream *st, void *buf, size_t sz)
         return st->vtbl->read(st, buf, sz);
 }
 
-static enum input_source istream_source(const unsigned char *sha1,
+static enum input_source istream_source(const struct object_id *oid,
                                         enum object_type *type,
                                         struct object_info *oi)
 {
@@ -114,7 +114,7 @@ static enum input_source istream_source(const unsigned char *sha1,
 
         oi->typep = type;
         oi->sizep = &size;
-        status = sha1_object_info_extended(sha1, oi, 0);
+        status = oid_object_info_extended(oid, oi, 0);
         if (status < 0)
                 return stream_error;
 
@@ -130,14 +130,14 @@ static enum input_source istream_source(const unsigned char *sha1,
         }
 }
 
-struct git_istream *open_istream(const unsigned char *sha1,
+struct git_istream *open_istream(const struct object_id *oid,
                                  enum object_type *type,
                                  unsigned long *size,
                                  struct stream_filter *filter)
 {
         struct git_istream *st;
         struct object_info oi = OBJECT_INFO_INIT;
-        const unsigned char *real = lookup_replace_object(sha1);
+        const struct object_id *real = lookup_replace_object(oid);
         enum input_source src = istream_source(real, type, &oi);
 
         if (src < 0)
@@ -335,7 +335,7 @@ static struct stream_vtbl loose_vtbl = {
 
 static open_method_decl(loose)
 {
-        st->u.loose.mapped = map_sha1_file(sha1, &st->u.loose.mapsize);
+        st->u.loose.mapped = map_sha1_file(oid->hash, &st->u.loose.mapsize);
         if (!st->u.loose.mapped)
                 return -1;
         if ((unpack_sha1_header(&st->z,
@@ -486,7 +486,7 @@ static struct stream_vtbl incore_vtbl = {
 
 static open_method_decl(incore)
 {
-        st->u.incore.buf = read_sha1_file_extended(sha1, type, &st->size, 0);
+        st->u.incore.buf = read_object_file_extended(oid, type, &st->size, 0);
         st->u.incore.read_ptr = 0;
         st->vtbl = &incore_vtbl;
 
@@ -507,7 +507,7 @@ int stream_blob_to_fd(int fd, const struct object_id *oid, struct stream_filter
         ssize_t kept = 0;
         int result = -1;
 
-        st = open_istream(oid->hash, &type, &sz, filter);
+        st = open_istream(oid, &type, &sz, filter);
         if (!st) {
                 if (filter)
                         free_stream_filter(filter);
diff --git a/streaming.h b/streaming.h
index 73c1d156b3..32f4626771 100644
--- a/streaming.h
+++ b/streaming.h
@@ -8,7 +8,7 @@
 /* opaque */
 struct git_istream;
 
-extern struct git_istream *open_istream(const unsigned char *, enum object_type *, unsigned long *, struct stream_filter *);
+extern struct git_istream *open_istream(const struct object_id *, enum object_type *, unsigned long *, struct stream_filter *);
 extern int close_istream(struct git_istream *);
 extern ssize_t read_istream(struct git_istream *, void *, size_t);
 
diff --git a/submodule-config.c b/submodule-config.c
index 602ba8ca8b..3f2075764f 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -520,7 +520,7 @@ static const struct submodule *config_from(struct submodule_cache *cache,
         if (submodule)
                 goto out;
 
-        config = read_sha1_file(oid.hash, &type, &config_size);
+        config = read_object_file(&oid, &type, &config_size);
         if (!config || type != OBJ_BLOB)
                 goto out;
 
diff --git a/submodule.c b/submodule.c
index 12a2503fda..a05c544e8d 100644
--- a/submodule.c
+++ b/submodule.c
@@ -540,9 +540,9 @@ static void show_submodule_header(struct diff_options *o, const char *path,
 
 output_header:
         strbuf_addf(&sb, "Submodule %s ", path);
-        strbuf_add_unique_abbrev(&sb, one->hash, DEFAULT_ABBREV);
+        strbuf_add_unique_abbrev(&sb, one, DEFAULT_ABBREV);
         strbuf_addstr(&sb, (fast_backward || fast_forward) ? ".." : "...");
-        strbuf_add_unique_abbrev(&sb, two->hash, DEFAULT_ABBREV);
+        strbuf_add_unique_abbrev(&sb, two, DEFAULT_ABBREV);
         if (message)
                 strbuf_addf(&sb, " %s\n", message);
         else
@@ -817,7 +817,7 @@ static int check_has_commit(const struct object_id *oid, void *data)
 {
         struct has_commit_data *cb = data;
 
-        enum object_type type = sha1_object_info(oid->hash, NULL);
+        enum object_type type = oid_object_info(oid, NULL);
 
         switch (type) {
         case OBJ_COMMIT:
diff --git a/tag.c b/tag.c
index 66210fd477..86b1dcbb82 100644
--- a/tag.c
+++ b/tag.c
@@ -41,20 +41,20 @@ int gpg_verify_tag(const struct object_id *oid, const char *name_to_report,
         unsigned long size;
         int ret;
 
-        type = sha1_object_info(oid->hash, NULL);
+        type = oid_object_info(oid, NULL);
         if (type != OBJ_TAG)
                 return error("%s: cannot verify a non-tag object of type %s.",
                                 name_to_report ?
                                 name_to_report :
-                                find_unique_abbrev(oid->hash, DEFAULT_ABBREV),
+                                find_unique_abbrev(oid, DEFAULT_ABBREV),
                                 type_name(type));
 
-        buf = read_sha1_file(oid->hash, &type, &size);
+        buf = read_object_file(oid, &type, &size);
         if (!buf)
                 return error("%s: unable to read file.",
                                 name_to_report ?
                                 name_to_report :
-                                find_unique_abbrev(oid->hash, DEFAULT_ABBREV));
+                                find_unique_abbrev(oid, DEFAULT_ABBREV));
 
         ret = run_gpg_verify(buf, size, flags);
 
@@ -182,7 +182,7 @@ int parse_tag(struct tag *item)
 
         if (item->object.parsed)
                 return 0;
-        data = read_sha1_file(item->object.oid.hash, &type, &size);
+        data = read_object_file(&item->object.oid, &type, &size);
         if (!data)
                 return error("Could not read %s",
                              oid_to_hex(&item->object.oid));
diff --git a/transport.c b/transport.c
index 00d48b5b56..b9dfa11bd2 100644
--- a/transport.c
+++ b/transport.c
@@ -367,7 +367,7 @@ static void print_ok_ref_status(struct ref *ref, int porcelain, int summary_widt
                 char type;
                 const char *msg;
 
-                strbuf_add_unique_abbrev(&quickref, ref->old_oid.hash,
+                strbuf_add_unique_abbrev(&quickref, &ref->old_oid,
                                          DEFAULT_ABBREV);
                 if (ref->forced_update) {
                         strbuf_addstr(&quickref, "...");
@@ -378,7 +378,7 @@ static void print_ok_ref_status(struct ref *ref, int porcelain, int summary_widt
                         type = ' ';
                         msg = NULL;
                 }
-                strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash,
+                strbuf_add_unique_abbrev(&quickref, &ref->new_oid,
                                          DEFAULT_ABBREV);
 
                 print_ref_status(type, quickref.buf, ref, ref->peer_ref, msg,
@@ -461,7 +461,7 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count,
 static int measure_abbrev(const struct object_id *oid, int sofar)
 {
         char hex[GIT_MAX_HEXSZ + 1];
-        int w = find_unique_abbrev_r(hex, oid->hash, DEFAULT_ABBREV);
+        int w = find_unique_abbrev_r(hex, oid, DEFAULT_ABBREV);
 
         return (w < sofar) ? sofar : w;
 }
diff --git a/tree-walk.c b/tree-walk.c
index 63a87ed666..e11b3063af 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -84,8 +84,7 @@ void *fill_tree_descriptor(struct tree_desc *desc, const struct object_id *oid)
         void *buf = NULL;
 
         if (oid) {
-                buf = read_object_with_reference(oid->hash, tree_type, &size,
-                                                 NULL);
+                buf = read_object_with_reference(oid, tree_type, &size, NULL);
                 if (!buf)
                         die("unable to read tree %s", oid_to_hex(oid));
         }
@@ -492,7 +491,7 @@ struct dir_state {
         unsigned char sha1[20];
 };
 
-static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char *result, unsigned *mode)
+static int find_tree_entry(struct tree_desc *t, const char *name, struct object_id *result, unsigned *mode)
 {
         int namelen = strlen(name);
         while (t->size) {
@@ -511,7 +510,7 @@ static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char
                 if (cmp < 0)
                         break;
                 if (entrylen == namelen) {
-                        hashcpy(result, oid->hash);
+                        oidcpy(result, oid);
                         return 0;
                 }
                 if (name[entrylen] != '/')
@@ -519,27 +518,27 @@ static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char
                 if (!S_ISDIR(*mode))
                         break;
                 if (++entrylen == namelen) {
-                        hashcpy(result, oid->hash);
+                        oidcpy(result, oid);
                         return 0;
                 }
-                return get_tree_entry(oid->hash, name + entrylen, result, mode);
+                return get_tree_entry(oid, name + entrylen, result, mode);
         }
         return -1;
 }
 
-int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned char *sha1, unsigned *mode)
+int get_tree_entry(const struct object_id *tree_oid, const char *name, struct object_id *oid, unsigned *mode)
 {
         int retval;
         void *tree;
         unsigned long size;
-        unsigned char root[20];
+        struct object_id root;
 
-        tree = read_object_with_reference(tree_sha1, tree_type, &size, root);
+        tree = read_object_with_reference(tree_oid, tree_type, &size, &root);
         if (!tree)
                 return -1;
 
         if (name[0] == '\0') {
-                hashcpy(sha1, root);
+                oidcpy(oid, &root);
                 free(tree);
                 return 0;
         }
@@ -549,7 +548,7 @@ int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned ch
         } else {
                 struct tree_desc t;
                 init_tree_desc(&t, tree, size);
-                retval = find_tree_entry(&t, name, sha1, mode);
+                retval = find_tree_entry(&t, name, oid, mode);
         }
         free(tree);
         return retval;
@@ -583,14 +582,14 @@ enum follow_symlinks_result get_tree_entry_follow_symlinks(unsigned char *tree_s
         struct dir_state *parents = NULL;
         size_t parents_alloc = 0;
         size_t i, parents_nr = 0;
-        unsigned char current_tree_sha1[20];
+        struct object_id current_tree_oid;
         struct strbuf namebuf = STRBUF_INIT;
         struct tree_desc t;
         int follows_remaining = GET_TREE_ENTRY_FOLLOW_SYMLINKS_MAX_LINKS;
 
         init_tree_desc(&t, NULL, 0UL);
         strbuf_addstr(&namebuf, name);
-        hashcpy(current_tree_sha1, tree_sha1);
+        hashcpy(current_tree_oid.hash, tree_sha1);
 
         while (1) {
                 int find_result;
@@ -599,22 +598,22 @@ enum follow_symlinks_result get_tree_entry_follow_symlinks(unsigned char *tree_s
 
                 if (!t.buffer) {
                         void *tree;
-                        unsigned char root[20];
+                        struct object_id root;
                         unsigned long size;
-                        tree = read_object_with_reference(current_tree_sha1,
+                        tree = read_object_with_reference(&current_tree_oid,
                                                           tree_type, &size,
-                                                          root);
+                                                          &root);
                         if (!tree)
                                 goto done;
 
                         ALLOC_GROW(parents, parents_nr + 1, parents_alloc);
                         parents[parents_nr].tree = tree;
                         parents[parents_nr].size = size;
-                        hashcpy(parents[parents_nr].sha1, root);
+                        hashcpy(parents[parents_nr].sha1, root.hash);
                         parents_nr++;
 
                         if (namebuf.buf[0] == '\0') {
-                                hashcpy(result, root);
+                                hashcpy(result, root.hash);
                                 retval = FOUND;
                                 goto done;
                         }
@@ -671,14 +670,14 @@ enum follow_symlinks_result get_tree_entry_follow_symlinks(unsigned char *tree_s
 
                 /* Look up the first (or only) path component in the tree. */
                 find_result = find_tree_entry(&t, namebuf.buf,
-                                              current_tree_sha1, mode);
+                                              &current_tree_oid, mode);
                 if (find_result) {
                         goto done;
                 }
 
                 if (S_ISDIR(*mode)) {
                         if (!remainder) {
-                                hashcpy(result, current_tree_sha1);
+                                hashcpy(result, current_tree_oid.hash);
                                 retval = FOUND;
                                 goto done;
                         }
@@ -688,7 +687,7 @@ enum follow_symlinks_result get_tree_entry_follow_symlinks(unsigned char *tree_s
                                       1 + first_slash - namebuf.buf);
                 } else if (S_ISREG(*mode)) {
                         if (!remainder) {
-                                hashcpy(result, current_tree_sha1);
+                                hashcpy(result, current_tree_oid.hash);
                                 retval = FOUND;
                         } else {
                                 retval = NOT_DIR;
@@ -714,8 +713,8 @@ enum follow_symlinks_result get_tree_entry_follow_symlinks(unsigned char *tree_s
                          */
                         retval = DANGLING_SYMLINK;
 
-                        contents = read_sha1_file(current_tree_sha1, &type,
-                                                  &link_len);
+                        contents = read_object_file(&current_tree_oid, &type,
+                                                    &link_len);
 
                         if (!contents)
                                 goto done;
diff --git a/tree-walk.h b/tree-walk.h
index b6bd1b4ccf..4617deeb0e 100644
--- a/tree-walk.h
+++ b/tree-walk.h
@@ -79,7 +79,7 @@ struct traverse_info {
         int show_all_errors;
 };
 
-int get_tree_entry(const unsigned char *, const char *, unsigned char *, unsigned *);
+int get_tree_entry(const struct object_id *, const char *, struct object_id *, unsigned *);
 extern char *make_traverse_path(char *path, const struct traverse_info *info, const struct name_entry *n);
 extern void setup_traverse_info(struct traverse_info *info, const char *base);
 
diff --git a/tree.c b/tree.c
index b224115e0f..1c68ea586b 100644
--- a/tree.c
+++ b/tree.c
@@ -10,7 +10,7 @@
 const char *tree_type = "tree";
 
 static int read_one_entry_opt(struct index_state *istate,
-                              const unsigned char *sha1,
+                              const struct object_id *oid,
                               const char *base, int baselen,
                               const char *pathname,
                               unsigned mode, int stage, int opt)
@@ -31,16 +31,16 @@ static int read_one_entry_opt(struct index_state *istate,
         ce->ce_namelen = baselen + len;
         memcpy(ce->name, base, baselen);
         memcpy(ce->name + baselen, pathname, len+1);
-        hashcpy(ce->oid.hash, sha1);
+        oidcpy(&ce->oid, oid);
         return add_index_entry(istate, ce, opt);
 }
 
-static int read_one_entry(const unsigned char *sha1, struct strbuf *base,
+static int read_one_entry(const struct object_id *oid, struct strbuf *base,
                           const char *pathname, unsigned mode, int stage,
                           void *context)
 {
         struct index_state *istate = context;
-        return read_one_entry_opt(istate, sha1, base->buf, base->len, pathname,
+        return read_one_entry_opt(istate, oid, base->buf, base->len, pathname,
                                   mode, stage,
                                   ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);
 }
@@ -49,12 +49,12 @@ static int read_one_entry(const unsigned char *sha1, struct strbuf *base,
  * This is used when the caller knows there is no existing entries at
  * the stage that will conflict with the entry being added.
  */
-static int read_one_entry_quick(const unsigned char *sha1, struct strbuf *base,
+static int read_one_entry_quick(const struct object_id *oid, struct strbuf *base,
                                 const char *pathname, unsigned mode, int stage,
                                 void *context)
 {
         struct index_state *istate = context;
-        return read_one_entry_opt(istate, sha1, base->buf, base->len, pathname,
+        return read_one_entry_opt(istate, oid, base->buf, base->len, pathname,
                                   mode, stage,
                                   ADD_CACHE_JUST_APPEND);
 }
@@ -83,7 +83,7 @@ static int read_tree_1(struct tree *tree, struct strbuf *base,
                                 continue;
                 }
 
-                switch (fn(entry.oid->hash, base,
+                switch (fn(entry.oid, base,
                            entry.path, entry.mode, stage, context)) {
                 case 0:
                         continue;
@@ -219,7 +219,7 @@ int parse_tree_gently(struct tree *item, int quiet_on_missing)
 
         if (item->object.parsed)
                 return 0;
-        buffer = read_sha1_file(item->object.oid.hash, &type, &size);
+        buffer = read_object_file(&item->object.oid, &type, &size);
         if (!buffer)
                 return quiet_on_missing ? -1 :
                         error("Could not read %s",
diff --git a/tree.h b/tree.h
index 744e6dc2ac..e2a80be4ef 100644
--- a/tree.h
+++ b/tree.h
@@ -27,7 +27,7 @@ void free_tree_buffer(struct tree *tree);
 struct tree *parse_tree_indirect(const struct object_id *oid);
 
 #define READ_TREE_RECURSIVE 1
-typedef int (*read_tree_fn_t)(const unsigned char *, struct strbuf *, const char *, unsigned int, int, void *);
+typedef int (*read_tree_fn_t)(const struct object_id *, struct strbuf *, const char *, unsigned int, int, void *);
 
 extern int read_tree_recursive(struct tree *tree,
                                const char *base, int baselen,
diff --git a/wt-status.c b/wt-status.c
index 66f4234af1..50815e5faf 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1188,7 +1188,7 @@ static void abbrev_sha1_in_line(struct strbuf *line)
                 strbuf_trim(split[1]);
                 if (!get_oid(split[1]->buf, &oid)) {
                         strbuf_reset(split[1]);
-                        strbuf_add_unique_abbrev(split[1], oid.hash,
+                        strbuf_add_unique_abbrev(split[1], &oid,
                                                  DEFAULT_ABBREV);
                         strbuf_addch(split[1], ' ');
                         strbuf_reset(line);
@@ -1350,7 +1350,7 @@ static void show_cherry_pick_in_progress(struct wt_status *s,
                                         const char *color)
 {
         status_printf_ln(s, color, _("You are currently cherry-picking commit %s."),
-                        find_unique_abbrev(state->cherry_pick_head_sha1, DEFAULT_ABBREV));
+                        find_unique_abbrev(&state->cherry_pick_head_oid, DEFAULT_ABBREV));
         if (s->hints) {
                 if (has_unmerged(s))
                         status_printf_ln(s, color,
@@ -1369,7 +1369,7 @@ static void show_revert_in_progress(struct wt_status *s,
                                         const char *color)
 {
         status_printf_ln(s, color, _("You are currently reverting commit %s."),
-                         find_unique_abbrev(state->revert_head_sha1, DEFAULT_ABBREV));
+                         find_unique_abbrev(&state->revert_head_oid, DEFAULT_ABBREV));
         if (s->hints) {
                 if (has_unmerged(s))
                         status_printf_ln(s, color,
@@ -1422,7 +1422,7 @@ static char *get_branch(const struct worktree *wt, const char *path)
                 ;
         else if (!get_oid_hex(sb.buf, &oid)) {
                 strbuf_reset(&sb);
-                strbuf_add_unique_abbrev(&sb, oid.hash, DEFAULT_ABBREV);
+                strbuf_add_unique_abbrev(&sb, &oid, DEFAULT_ABBREV);
         } else if (!strcmp(sb.buf, "detached HEAD")) /* rebase */
                 goto got_nothing;
         else                        /* bisect */
@@ -1459,7 +1459,7 @@ static int grab_1st_switch(struct object_id *ooid, struct object_id *noid,
         if (!strcmp(cb->buf.buf, "HEAD")) {
                 /* HEAD is relative. Resolve it to the right reflog entry. */
                 strbuf_reset(&cb->buf);
-                strbuf_add_unique_abbrev(&cb->buf, noid->hash, DEFAULT_ABBREV);
+                strbuf_add_unique_abbrev(&cb->buf, noid, DEFAULT_ABBREV);
         }
         return 1;
 }
@@ -1489,10 +1489,10 @@ static void wt_status_get_detached_from(struct wt_status_state *state)
                 state->detached_from = xstrdup(from);
         } else
                 state->detached_from =
-                        xstrdup(find_unique_abbrev(cb.noid.hash, DEFAULT_ABBREV));
-        hashcpy(state->detached_sha1, cb.noid.hash);
+                        xstrdup(find_unique_abbrev(&cb.noid, DEFAULT_ABBREV));
+        oidcpy(&state->detached_oid, &cb.noid);
         state->detached_at = !get_oid("HEAD", &oid) &&
-                             !hashcmp(oid.hash, state->detached_sha1);
+                             !oidcmp(&oid, &state->detached_oid);
 
         free(ref);
         strbuf_release(&cb.buf);
@@ -1551,13 +1551,13 @@ void wt_status_get_state(struct wt_status_state *state,
         } else if (!stat(git_path_cherry_pick_head(), &st) &&
                         !get_oid("CHERRY_PICK_HEAD", &oid)) {
                 state->cherry_pick_in_progress = 1;
-                hashcpy(state->cherry_pick_head_sha1, oid.hash);
+                oidcpy(&state->cherry_pick_head_oid, &oid);
         }
         wt_status_check_bisect(NULL, state);
         if (!stat(git_path_revert_head(), &st) &&
             !get_oid("REVERT_HEAD", &oid)) {
                 state->revert_in_progress = 1;
-                hashcpy(state->revert_head_sha1, oid.hash);
+                oidcpy(&state->revert_head_oid, &oid);
         }
 
         if (get_detached_from)
diff --git a/wt-status.h b/wt-status.h
index ea2456daf2..430770b854 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -118,9 +118,9 @@ struct wt_status_state {
         char *branch;
         char *onto;
         char *detached_from;
-        unsigned char detached_sha1[20];
-        unsigned char revert_head_sha1[20];
-        unsigned char cherry_pick_head_sha1[20];
+        struct object_id detached_oid;
+        struct object_id revert_head_oid;
+        struct object_id cherry_pick_head_oid;
 };
 
 size_t wt_status_locate_end(const char *s, size_t len);
diff --git a/xdiff-interface.c b/xdiff-interface.c
index 770e1f7f81..9315bc0ede 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -191,7 +191,7 @@ void read_mmblob(mmfile_t *ptr, const struct object_id *oid)
                 return;
         }
 
-        ptr->ptr = read_sha1_file(oid->hash, &type, &size);
+        ptr->ptr = read_object_file(oid, &type, &size);
         if (!ptr->ptr || type != OBJ_BLOB)
                 die("unable to read blob object %s", oid_to_hex(oid));
         ptr->size = size;