Skip to content

Commit 13be3e3

Browse files
committed
Reword "detached HEAD" notification
The old "advice" message explained how to create a branch after going into a detached HEAD state but didn't make it clear why the user may want to do so. Also "moving to ... which isn't a local branch" was unclear if it is complaining, if it is describing the new state, or if it is explaining why the HEAD is detached (the true reason is the last one). Give the established phrase 'detached HEAD' first to make it easy for users to look up the concept in documentation, and briefly describe what can be done in the state (i.e. play around without having to clean up) before telling the user how to keep what was done during the temporary state. Allow the long description to be hidden by setting advice.detachedHead configuration to false. We might want to customize the advice depending on how the commit to check out was spelled (e.g. instead of "new-branch-name", we way want to say "topic" when "git checkout origin/topic" triggered this message) in later updates, but this encapsulates that into a separate function and it should be a good first step. Signed-off-by: Junio C Hamano <[email protected]>
1 parent b2c2e4c commit 13be3e3

File tree

5 files changed

+46
-12
lines changed

5 files changed

+46
-12
lines changed

Documentation/config.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ advice.*::
138138
Advice on how to set your identity configuration when
139139
your information is guessed from the system username and
140140
domain name. Default: true.
141+
142+
detachedHead::
143+
Advice shown when you used linkgit::git-checkout[1] to
144+
move to the detach HEAD state, to instruct how to create
145+
a local branch after the fact. Default: true.
141146
--
142147

143148
core.fileMode::

advice.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ int advice_status_hints = 1;
55
int advice_commit_before_merge = 1;
66
int advice_resolve_conflict = 1;
77
int advice_implicit_identity = 1;
8+
int advice_detached_head = 1;
89

910
static struct {
1011
const char *name;
@@ -15,6 +16,7 @@ static struct {
1516
{ "commitbeforemerge", &advice_commit_before_merge },
1617
{ "resolveconflict", &advice_resolve_conflict },
1718
{ "implicitidentity", &advice_implicit_identity },
19+
{ "detachedhead", &advice_detached_head },
1820
};
1921

2022
int git_default_advice_config(const char *var, const char *value)

advice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extern int advice_status_hints;
88
extern int advice_commit_before_merge;
99
extern int advice_resolve_conflict;
1010
extern int advice_implicit_identity;
11+
extern int advice_detached_head;
1112

1213
int git_default_advice_config(const char *var, const char *value);
1314

builtin-checkout.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,20 @@ static void report_tracking(struct branch_info *new)
488488
strbuf_release(&sb);
489489
}
490490

491+
static void detach_advice(const char *old_path, const char *new_name)
492+
{
493+
const char fmt[] =
494+
"Note: checking out '%s'.\n\n"
495+
"You are in 'detached HEAD' state. You can look around, make experimental\n"
496+
"changes and commit them, and you can discard any commits you make in this\n"
497+
"state without impacting any branches by performing another checkout.\n\n"
498+
"If you want to create a new branch to retain commits you create, you may\n"
499+
"do so (now or later) by using -b with the checkout command again. Example:\n\n"
500+
" git checkout -b new_branch_name\n\n";
501+
502+
fprintf(stderr, fmt, new_name);
503+
}
504+
491505
static void update_refs_for_switch(struct checkout_opts *opts,
492506
struct branch_info *old,
493507
struct branch_info *new)
@@ -522,8 +536,8 @@ static void update_refs_for_switch(struct checkout_opts *opts,
522536
update_ref(msg.buf, "HEAD", new->commit->object.sha1, NULL,
523537
REF_NODEREF, DIE_ON_ERR);
524538
if (!opts->quiet) {
525-
if (old->path)
526-
fprintf(stderr, "Note: moving to '%s' which isn't a local branch\nIf you want to create a new branch from this checkout, you may do so\n(now or later) by using -b with the checkout command again. Example:\n git checkout -b <new_branch_name>\n", new->name);
539+
if (old->path && advice_detached_head)
540+
detach_advice(old->path, new->name);
527541
describe_detached_head("HEAD is now at", new->commit);
528542
}
529543
}

t/t7201-co.sh

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -166,19 +166,31 @@ test_expect_success 'checkout -m with merge conflict' '
166166
! test -s current
167167
'
168168

169-
test_expect_success 'checkout to detach HEAD' '
169+
test_expect_success 'checkout to detach HEAD (with advice declined)' '
170170
171+
git config advice.detachedHead false &&
171172
git checkout -f renamer && git clean -f &&
172173
git checkout renamer^ 2>messages &&
173-
(cat >messages.expect <<EOF
174-
Note: moving to '\''renamer^'\'' which isn'\''t a local branch
175-
If you want to create a new branch from this checkout, you may do so
176-
(now or later) by using -b with the checkout command again. Example:
177-
git checkout -b <new_branch_name>
178-
HEAD is now at 7329388... Initial A one, A two
179-
EOF
180-
) &&
181-
test_cmp messages.expect messages &&
174+
grep "HEAD is now at 7329388" messages &&
175+
test 1 -eq $(wc -l <messages) &&
176+
H=$(git rev-parse --verify HEAD) &&
177+
M=$(git show-ref -s --verify refs/heads/master) &&
178+
test "z$H" = "z$M" &&
179+
if git symbolic-ref HEAD >/dev/null 2>&1
180+
then
181+
echo "OOPS, HEAD is still symbolic???"
182+
false
183+
else
184+
: happy
185+
fi
186+
'
187+
188+
test_expect_success 'checkout to detach HEAD' '
189+
git config advice.detachedHead true &&
190+
git checkout -f renamer && git clean -f &&
191+
git checkout renamer^ 2>messages &&
192+
grep "HEAD is now at 7329388" messages &&
193+
test 1 -lt $(wc -l <messages) &&
182194
H=$(git rev-parse --verify HEAD) &&
183195
M=$(git show-ref -s --verify refs/heads/master) &&
184196
test "z$H" = "z$M" &&

0 commit comments

Comments
 (0)