Skip to content

Commit 35f0383

Browse files
OneDeuxTriSeiGogitster
authored andcommitted
worktree add: introduce "try --orphan" hint
Add a new advice/hint in `git worktree add` for when the user tries to create a new worktree from a reference that doesn't exist. Current Behavior: % git init foo Initialized empty Git repository in /path/to/foo/ % touch file % git -C foo commit -q -a -m "test commit" % git -C foo switch --orphan norefbranch % git -C foo worktree add newbranch/ Preparing worktree (new branch 'newbranch') fatal: invalid reference: HEAD % New Behavior: % git init --bare foo Initialized empty Git repository in /path/to/foo/ % touch file % git -C foo commit -q -a -m "test commit" % git -C foo switch --orphan norefbranch % git -C foo worktree add newbranch/ Preparing worktree (new branch 'newbranch') hint: If you meant to create a worktree containing a new orphan branch hint: (branch with no commits) for this repository, you can do so hint: using the --orphan option: hint: hint: git worktree add --orphan newbranch/ hint: hint: Disable this message with "git config advice.worktreeAddOrphan false" fatal: invalid reference: HEAD % git -C foo worktree add -b newbranch2 new_wt/ Preparing worktree (new branch 'newbranch') hint: If you meant to create a worktree containing a new orphan branch hint: (branch with no commits) for this repository, you can do so hint: using the --orphan option: hint: hint: git worktree add --orphan -b newbranch2 new_wt/ hint: hint: Disable this message with "git config advice.worktreeAddOrphan false" fatal: invalid reference: HEAD % Signed-off-by: Jacob Abel <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7ab8918 commit 35f0383

File tree

5 files changed

+69
-0
lines changed

5 files changed

+69
-0
lines changed

Documentation/config/advice.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,8 @@ advice.*::
138138
checkout.
139139
diverging::
140140
Advice shown when a fast-forward is not possible.
141+
worktreeAddOrphan::
142+
Advice shown when a user tries to create a worktree from an
143+
invalid reference, to instruct how to create a new orphan
144+
branch instead.
141145
--

advice.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ static struct {
7878
[ADVICE_SUBMODULES_NOT_UPDATED] = { "submodulesNotUpdated", 1 },
7979
[ADVICE_UPDATE_SPARSE_PATH] = { "updateSparsePath", 1 },
8080
[ADVICE_WAITING_FOR_EDITOR] = { "waitingForEditor", 1 },
81+
[ADVICE_WORKTREE_ADD_ORPHAN] = { "worktreeAddOrphan", 1 },
8182
};
8283

8384
static const char turn_off_instructions[] =

advice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ struct string_list;
4949
ADVICE_UPDATE_SPARSE_PATH,
5050
ADVICE_WAITING_FOR_EDITOR,
5151
ADVICE_SKIPPED_CHERRY_PICKS,
52+
ADVICE_WORKTREE_ADD_ORPHAN,
5253
};
5354

5455
int git_default_advice_config(const char *var, const char *value);

builtin/worktree.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "cache.h"
22
#include "abspath.h"
3+
#include "advice.h"
34
#include "checkout.h"
45
#include "config.h"
56
#include "builtin.h"
@@ -39,6 +40,20 @@
3940
#define BUILTIN_WORKTREE_UNLOCK_USAGE \
4041
N_("git worktree unlock <worktree>")
4142

43+
#define WORKTREE_ADD_ORPHAN_WITH_DASH_B_HINT_TEXT \
44+
_("If you meant to create a worktree containing a new orphan branch\n" \
45+
"(branch with no commits) for this repository, you can do so\n" \
46+
"using the --orphan flag:\n" \
47+
"\n" \
48+
" git worktree add --orphan -b %s %s\n")
49+
50+
#define WORKTREE_ADD_ORPHAN_NO_DASH_B_HINT_TEXT \
51+
_("If you meant to create a worktree containing a new orphan branch\n" \
52+
"(branch with no commits) for this repository, you can do so\n" \
53+
"using the --orphan flag:\n" \
54+
"\n" \
55+
" git worktree add --orphan %s\n")
56+
4257
static const char * const git_worktree_usage[] = {
4358
BUILTIN_WORKTREE_ADD_USAGE,
4459
BUILTIN_WORKTREE_LIST_USAGE,
@@ -634,6 +649,7 @@ static int add(int ac, const char **av, const char *prefix)
634649
const char *opt_track = NULL;
635650
const char *lock_reason = NULL;
636651
int keep_locked = 0;
652+
int used_new_branch_options;
637653
struct option options[] = {
638654
OPT__FORCE(&opts.force,
639655
N_("checkout <branch> even if already checked out in other worktree"),
@@ -686,6 +702,7 @@ static int add(int ac, const char **av, const char *prefix)
686702

687703
path = prefix_filename(prefix, av[0]);
688704
branch = ac < 2 ? "HEAD" : av[1];
705+
used_new_branch_options = new_branch || new_branch_force;
689706

690707
if (!strcmp(branch, "-"))
691708
branch = "@{-1}";
@@ -728,6 +745,15 @@ static int add(int ac, const char **av, const char *prefix)
728745
}
729746

730747
if (!opts.orphan && !lookup_commit_reference_by_name(branch)) {
748+
int attempt_hint = !opts.quiet && (ac < 2);
749+
if (attempt_hint && used_new_branch_options) {
750+
advise_if_enabled(ADVICE_WORKTREE_ADD_ORPHAN,
751+
WORKTREE_ADD_ORPHAN_WITH_DASH_B_HINT_TEXT,
752+
new_branch, path);
753+
} else if (attempt_hint) {
754+
advise_if_enabled(ADVICE_WORKTREE_ADD_ORPHAN,
755+
WORKTREE_ADD_ORPHAN_NO_DASH_B_HINT_TEXT, path);
756+
}
731757
die(_("invalid reference: %s"), branch);
732758
}
733759

t/t2400-worktree-add.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,43 @@ test_expect_success '"add" worktree with orphan branch, lock, and reason' '
401401
test_cmp expect .git/worktrees/orphan-with-lock-reason/locked
402402
'
403403

404+
# Note: Quoted arguments containing spaces are not supported.
405+
test_wt_add_orphan_hint () {
406+
local context="$1" &&
407+
local use_branch=$2 &&
408+
shift 2 &&
409+
local opts="$*" &&
410+
test_expect_success "'worktree add' show orphan hint in bad/orphan HEAD w/ $context" '
411+
test_when_finished "rm -rf repo" &&
412+
git init repo &&
413+
(cd repo && test_commit commit) &&
414+
git -C repo switch --orphan noref &&
415+
test_must_fail git -C repo worktree add $opts foobar/ 2>actual &&
416+
! grep "error: unknown switch" actual &&
417+
grep "hint: If you meant to create a worktree containing a new orphan branch" actual &&
418+
if [ $use_branch -eq 1 ]
419+
then
420+
grep -E "^hint:\s+git worktree add --orphan -b \S+ \S+\s*$" actual
421+
else
422+
grep -E "^hint:\s+git worktree add --orphan \S+\s*$" actual
423+
fi
424+
425+
'
426+
}
427+
428+
test_wt_add_orphan_hint 'no opts' 0
429+
test_wt_add_orphan_hint '-b' 1 -b foobar_branch
430+
test_wt_add_orphan_hint '-B' 1 -B foobar_branch
431+
432+
test_expect_success "'worktree add' doesn't show orphan hint in bad/orphan HEAD w/ --quiet" '
433+
test_when_finished "rm -rf repo" &&
434+
git init repo &&
435+
(cd repo && test_commit commit) &&
436+
test_must_fail git -C repo worktree add --quiet foobar_branch foobar/ 2>actual &&
437+
! grep "error: unknown switch" actual &&
438+
! grep "hint: If you meant to create a worktree containing a new orphan branch" actual
439+
'
440+
404441
test_expect_success 'local clone from linked checkout' '
405442
git clone --local here here-clone &&
406443
( cd here-clone && git fsck )

0 commit comments

Comments
 (0)