sha1-name.c: for ":/", find detached HEAD commits

This patch broadens the set of commits matched by ":/<pattern>" to include commits reachable from HEAD but not any named ref. This avoids surprising behavior when working with a detached HEAD and trying to refer to a commit that was recently created and only exists within the detached state. If multiple worktrees exist, only the current worktree's HEAD is considered reachable. This is consistent with the existing behavior for other per-worktree refs: e.g., bisect refs are considered reachable, but only within the relevant worktree. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: William Chargin <wchargin@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

William Chargin committed Jul 11, 2018 at 22:49 UTC 6b3351e799f733561b98241f6ee88a9a72c13400
3 files changed +29 -1
Documentation/revisions.txt
+2 -1
@@ -180,7 +180,8 @@ existing tag object.
180 A colon, followed by a slash, followed by a text, names
181 a commit whose commit message matches the specified regular expression.
182 This name returns the youngest matching commit which is
183 - reachable from any ref. The regular expression can match any part of the
183 + reachable from any ref, including HEAD.
184 + The regular expression can match any part of the
185 commit message. To match messages starting with a string, one can use
186 e.g. ':/^foo'. The special sequence ':/!' is reserved for modifiers to what
187 is matched. ':/!-foo' performs a negative match, while ':/!!foo' matches a
sha1_name.c
+1
@@ -1649,6 +1649,7 @@ static int get_oid_with_context_1(const char *name,
1649 struct commit_list *list = NULL;
1650
1651 for_each_ref(handle_one_ref, &list);
1652 + head_ref(handle_one_ref, &list);
1653 commit_list_sort_by_date(&list);
1654 return get_oid_oneline(name + 2, oid, list);
1655 }
t/t4208-log-magic-pathspec.sh
+26
@@ -25,6 +25,32 @@ test_expect_success '"git log :/a -- " should not be ambiguous' '
25 git log :/a --
26 '
27
28 +test_expect_success '"git log :/detached -- " should find a commit only in HEAD' '
29 + test_when_finished "git checkout master" &&
30 + git checkout --detach &&
31 + # Must manually call `test_tick` instead of using `test_commit`,
32 + # because the latter additionally creates a tag, which would make
33 + # the commit reachable not only via HEAD.
34 + test_tick &&
35 + git commit --allow-empty -m detached &&
36 + test_tick &&
37 + git commit --allow-empty -m something-else &&
38 + git log :/detached --
39 +'
40 +
41 +test_expect_success '"git log :/detached -- " should not find an orphaned commit' '
42 + test_must_fail git log :/detached --
43 +'
44 +
45 +test_expect_success '"git log :/detached -- " should find HEAD only of own worktree' '
46 + git worktree add other-tree HEAD &&
47 + git -C other-tree checkout --detach &&
48 + test_tick &&
49 + git -C other-tree commit --allow-empty -m other-detached &&
50 + git -C other-tree log :/other-detached -- &&
51 + test_must_fail git log :/other-detached --
52 +'
53 +
54 test_expect_success '"git log -- :/a" should not be ambiguous' '
55 git log -- :/a
56 '