worktree add: stop reading ".git/HEAD"

The function can_use_local_refs() prints a warning if there are no local branches and HEAD is invalid or points to an unborn branch. As part of the warning it prints the contents of ".git/HEAD". In a repository using the reftable backend HEAD is not stored in the filesystem so reading that file is pointless. In a repository using the files backend it is unclear how useful printing it is - it would be better to diagnose the problem for the user. For now, simplify the warning by not printing the file contents and adjust the relevant test case accordingly. Also fixup the test case to use test_grep so that anyone trying to debug a test failure in the future is not met by a wall of silence. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Phillip Wood committed Mar 26, 2026 at 14:16 UTC 8bad0e07e1eddff2268bc9be3368c9b5fee47915
2 files changed +14 -35
builtin/worktree.c
+2 -19
@@ -692,25 +692,8 @@ static int can_use_local_refs(const struct add_opts *opts)
692 if (refs_head_ref(get_main_ref_store(the_repository), first_valid_ref, NULL)) {
693 return 1;
694 } else if (refs_for_each_branch_ref(get_main_ref_store(the_repository), first_valid_ref, NULL)) {
695 - if (!opts->quiet) {
696 - struct strbuf path = STRBUF_INIT;
697 - struct strbuf contents = STRBUF_INIT;
698 - char *wt_gitdir = get_worktree_git_dir(NULL);
699 -
700 - strbuf_add_real_path(&path, wt_gitdir);
701 - strbuf_addstr(&path, "/HEAD");
702 - strbuf_read_file(&contents, path.buf, 64);
703 - strbuf_stripspace(&contents, NULL);
704 - strbuf_strip_suffix(&contents, "\n");
705 -
706 - warning(_("HEAD points to an invalid (or orphaned) reference.\n"
707 - "HEAD path: '%s'\n"
708 - "HEAD contents: '%s'"),
709 - path.buf, contents.buf);
710 - strbuf_release(&path);
711 - strbuf_release(&contents);
712 - free(wt_gitdir);
713 - }
695 + if (!opts->quiet)
696 + warning(_("HEAD points to an invalid (or orphaned) reference.\n"));
697 return 1;
698 }
699 return 0;
t/t2400-worktree-add.sh
+12 -16
@@ -987,7 +987,7 @@ test_dwim_orphan () {
987 then
988 test_must_be_empty actual
989 else
990 - grep "$info_text" actual
990 + test_grep "$info_text" actual
991 fi
992 elif [ "$outcome" = "no_infer" ]
993 then
@@ -996,39 +996,35 @@ test_dwim_orphan () {
996 then
997 test_must_be_empty actual
998 else
999 - ! grep "$info_text" actual
999 + test_grep ! "$info_text" actual
1000 fi
1001 elif [ "$outcome" = "fetch_error" ]
1002 then
1003 test_must_fail git $dashc_args worktree add $args 2>actual &&
1004 - grep "$fetch_error_text" actual
1004 + test_grep "$fetch_error_text" actual
1005 elif [ "$outcome" = "fatal_orphan_bad_combo" ]
1006 then
1007 test_must_fail git $dashc_args worktree add $args 2>actual &&
1008 if [ $use_quiet -eq 1 ]
1009 then
1010 - ! grep "$info_text" actual
1010 + test_grep ! "$info_text" actual
1011 else
1012 - grep "$info_text" actual
1012 + test_grep "$info_text" actual
1013 fi &&
1014 - grep "$bad_combo_regex" actual
1014 + test_grep "$bad_combo_regex" actual
1015 elif [ "$outcome" = "warn_bad_head" ]
1016 then
1017 test_must_fail git $dashc_args worktree add $args 2>actual &&
1018 if [ $use_quiet -eq 1 ]
1019 then
1020 - grep "$invalid_ref_regex" actual &&
1021 - ! grep "$orphan_hint" actual
1020 + test_grep "$invalid_ref_regex" actual &&
1021 + test_grep ! "$orphan_hint" actual
1022 else
1023 - headpath=$(git $dashc_args rev-parse --path-format=absolute --git-path HEAD) &&
1024 - headcontents=$(cat "$headpath") &&
1025 - grep "HEAD points to an invalid (or orphaned) reference" actual &&
1026 - grep "HEAD path: .$headpath." actual &&
1027 - grep "HEAD contents: .$headcontents." actual &&
1028 - grep "$orphan_hint" actual &&
1029 - ! grep "$info_text" actual
1023 + test_grep "HEAD points to an invalid (or orphaned) reference" actual &&
1024 + test_grep "$orphan_hint" actual &&
1025 + test_grep ! "$info_text" actual
1026 fi &&
1031 - grep "$invalid_ref_regex" actual
1027 + test_grep "$invalid_ref_regex" actual
1028 else
1029 # Unreachable
1030 false