Git development
 help / color / mirror / Atom feed
From: Patrick Steinhardt <ps@pks.im>
To: Junio C Hamano <gitster@pobox.com>
Cc: "brian m. carlson" <sandals@crustytoothpaste.net>,
	git@vger.kernel.org, Adam Dinwoodie <adam@dinwoodie.org>
Subject: Re: [PATCH] setup: default hash algo to GIT_HASH_DEFAULT
Date: Mon, 9 Nov 2026 10:54:44 +0100	[thread overview]
Message-ID: <avGYZIFAmeSEP6ZS@pks.im> (raw)
In-Reply-To: <xmqqzevi218o.fsf@gitster.g>

On Sun, Nov 08, 2026 at 06:21:43PM -0800, Junio C Hamano wrote:
> Junio C Hamano <gitster@pobox.com> writes:
> 
> > I wonder what the "git init" command does wrt the reference storage
> > format (Patrick CC'ed for this)?  I am sure we do not convert from
> > reffiles to reftable on the fly at "git init" time.

Yeah, we don't, and I don't think that would be reasonable. I would very
much be surprised if git-init(1) migrated a repository's hash format,
ref storage format or object storage format. Those are long-running
operations and in the past, git-init(1) used to be somewhat idempotent
on an already-initialized repository. So I'd much rather have us migrate
explicitly, like we do with `git refs migrate`.

> I looked at setup.c:repository_format_configure() and found why
> your patch regresses, as well as a latent bug in the existing code.
> 
> First, REPOSITORY_FORMAT_INIT sets .hash_algo = GIT_HASH_DEFAULT,
> but read_repository_format() forces it to GIT_HASH_SHA1_LEGACY
> when version == -1 (no config yet), which is why new repositories
> kept getting SHA-1.
> 
> Second, unlike the ref-storage block right below it, which checks
> "else if (repo_fmt->version >= 0)" once between the explicit
> overrides and all default sources, the hash-algo block guards only
> the GIT_DEFAULT_HASH branch (repo_fmt->version < 0), leaving "else
> if (cfg.hash != GIT_HASH_UNKNOWN)" unguarded.
> 
> So init.defaultObjectFormat in ~/.gitconfig already corrupts an
> existing repository on re-init, and an unguarded "else" for
> GIT_HASH_DEFAULT falls into the same trap even without config.
> 
> Instead of starting the if/else if cascade like this:
> 
> 	if (repo_fmt->version >= 0 &&
> 	    hash != GIT_HASH_UNKNOWN &&
> 	    hash != repo_fmt->hash_algo)
> 		die(_("attempt to reinitialize repository with different hash"));
> 
> we should have started it like so:
> 
> 	if (repo_fmt->version >= 0) {
> 		if (hash != GIT_HASH_UNKNOWN && hash != repo_fmt->hash_algo)
> 			die(_("attempt to reinitialize repository with different hash"));
> 		/* otherwise happy */
> 	} else if ...
> 
> so that all the "set a new value from different sources like command
> line, environment, ~/.gitconfig, or the built-in default" would
> happen only when (repo_fmt->version < 0), probably?

Yeah, these blocks are overall quite hard to read. That's also the
reason why I re-did these checks for both the ref storage format and
then also used the new style for the object storage format. So my take
is that we should adapt the object format in a similar fashion so that
all of them use the same style, where we first detect the desired format
and then check whether we're trying to re-initialize with a different
object format towards the end of this function.

So something like this:

diff --git a/setup.c b/setup.c
index 61bcdafe82a..bf75abafeeb 100644
--- a/setup.c
+++ b/setup.c
@@ -2816,20 +2816,19 @@ static void repository_format_configure(struct repository_format *repo_fmt,
 	 * specify a different algorithm, as that could cause corruption.
 	 * Otherwise, if the user has specified one on the command line, use it.
 	 */
-	env = getenv(GIT_DEFAULT_HASH_ENVIRONMENT);
-	if (repo_fmt->version >= 0 && hash != GIT_HASH_UNKNOWN && hash != repo_fmt->hash_algo)
-		die(_("attempt to reinitialize repository with different hash"));
-	else if (hash != GIT_HASH_UNKNOWN)
-		repo_fmt->hash_algo = hash;
-	else if (env) {
+	if (hash != GIT_HASH_UNKNOWN) {
+		/* nothing to do */
+	} else if ((env = getenv(GIT_DEFAULT_HASH_ENVIRONMENT))) {
 		int env_algo = hash_algo_by_name(env);
 		if (env_algo == GIT_HASH_UNKNOWN)
 			die(_("unknown hash algorithm '%s'"), env);
 		if (repo_fmt->version < 0 ||
 		    repo_fmt->hash_algo == GIT_HASH_UNKNOWN)
 			repo_fmt->hash_algo = env_algo;
-	} else if (cfg.hash != GIT_HASH_UNKNOWN) {
-		repo_fmt->hash_algo = cfg.hash;
+	} else if (repo_fmt->version >= 0) {
+		hash = repo_fmt->hash_algo;
+	} else {
+		hash = GIT_HASH_DEFAULT;
 	}
 
 	/*
@@ -2899,6 +2898,8 @@ static void repository_format_configure(struct repository_format *repo_fmt,
 	 * current ref storage format does not change.
 	 */
 	if (repo_fmt->version >= 0) {
+		if (hash != repo_fmt->hash_algo)
+			die(_("attempt to reinitialize repository with different hash"));
 		if (ref_storage_format != repo_fmt->ref_storage_format)
 			die(_("attempt to reinitialize repository with different reference storage format"));
 		if ((ref_storage_payload || repo_fmt->ref_storage_payload) &&

Patrick

      reply	other threads:[~2026-11-09  9:54 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-06 16:50 Default object format for new repositories in Git v3 Adam Dinwoodie
2026-11-06 20:46 ` brian m. carlson
2026-11-08  1:16 ` [PATCH] setup: default hash algo to GIT_HASH_DEFAULT brian m. carlson
2026-11-08  4:42   ` Junio C Hamano
2026-11-08 14:38     ` brian m. carlson
2026-11-08 18:22   ` Junio C Hamano
2026-11-09  2:21     ` Junio C Hamano
2026-11-09  9:54       ` Patrick Steinhardt [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=avGYZIFAmeSEP6ZS@pks.im \
    --to=ps@pks.im \
    --cc=adam@dinwoodie.org \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=sandals@crustytoothpaste.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox