Skip to content

Commit ea3bb5c

Browse files
committed
git_repository_set_head: use tag name in reflog
When `git_repository_set_head` is provided a tag reference, update the reflog with the tag name, like we do with a branch. This helps consumers match the semantics of `git checkout tag`.
1 parent 33ea4aa commit ea3bb5c

File tree

2 files changed

+44
-41
lines changed

2 files changed

+44
-41
lines changed

src/repository.c

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2525,7 +2525,7 @@ static int checkout_message(git_buf *out, git_reference *old, const char *new)
25252525

25262526
git_buf_puts(out, " to ");
25272527

2528-
if (git_reference__is_branch(new))
2528+
if (git_reference__is_branch(new) || git_reference__is_tag(new))
25292529
git_buf_puts(out, git_reference__shorthand(new));
25302530
else
25312531
git_buf_puts(out, new);
@@ -2536,6 +2536,41 @@ static int checkout_message(git_buf *out, git_reference *old, const char *new)
25362536
return 0;
25372537
}
25382538

2539+
static int detach(git_repository *repo, const git_oid *id, const char *new)
2540+
{
2541+
int error;
2542+
git_buf log_message = GIT_BUF_INIT;
2543+
git_object *object = NULL, *peeled = NULL;
2544+
git_reference *new_head = NULL, *current = NULL;
2545+
2546+
assert(repo && id);
2547+
2548+
if ((error = git_reference_lookup(&current, repo, GIT_HEAD_FILE)) < 0)
2549+
return error;
2550+
2551+
if ((error = git_object_lookup(&object, repo, id, GIT_OBJ_ANY)) < 0)
2552+
goto cleanup;
2553+
2554+
if ((error = git_object_peel(&peeled, object, GIT_OBJ_COMMIT)) < 0)
2555+
goto cleanup;
2556+
2557+
if (new == NULL)
2558+
new = git_oid_tostr_s(git_object_id(peeled));
2559+
2560+
if ((error = checkout_message(&log_message, current, new)) < 0)
2561+
goto cleanup;
2562+
2563+
error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), true, git_buf_cstr(&log_message));
2564+
2565+
cleanup:
2566+
git_buf_free(&log_message);
2567+
git_object_free(object);
2568+
git_object_free(peeled);
2569+
git_reference_free(current);
2570+
git_reference_free(new_head);
2571+
return error;
2572+
}
2573+
25392574
int git_repository_set_head(
25402575
git_repository* repo,
25412576
const char* refname)
@@ -2567,7 +2602,8 @@ int git_repository_set_head(
25672602
error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE,
25682603
git_reference_name(ref), true, git_buf_cstr(&log_message));
25692604
} else {
2570-
error = git_repository_set_head_detached(repo, git_reference_target(ref));
2605+
error = detach(repo, git_reference_target(ref),
2606+
git_reference_is_tag(ref) ? refname : NULL);
25712607
}
25722608
} else if (git_reference__is_branch(refname)) {
25732609
error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, refname,
@@ -2582,41 +2618,6 @@ int git_repository_set_head(
25822618
return error;
25832619
}
25842620

2585-
static int detach(git_repository *repo, const git_oid *id, const char *from)
2586-
{
2587-
int error;
2588-
git_buf log_message = GIT_BUF_INIT;
2589-
git_object *object = NULL, *peeled = NULL;
2590-
git_reference *new_head = NULL, *current = NULL;
2591-
2592-
assert(repo && id);
2593-
2594-
if ((error = git_reference_lookup(&current, repo, GIT_HEAD_FILE)) < 0)
2595-
return error;
2596-
2597-
if ((error = git_object_lookup(&object, repo, id, GIT_OBJ_ANY)) < 0)
2598-
goto cleanup;
2599-
2600-
if ((error = git_object_peel(&peeled, object, GIT_OBJ_COMMIT)) < 0)
2601-
goto cleanup;
2602-
2603-
if (from == NULL)
2604-
from = git_oid_tostr_s(git_object_id(peeled));
2605-
2606-
if ((error = checkout_message(&log_message, current, from)) < 0)
2607-
goto cleanup;
2608-
2609-
error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), true, git_buf_cstr(&log_message));
2610-
2611-
cleanup:
2612-
git_buf_free(&log_message);
2613-
git_object_free(object);
2614-
git_object_free(peeled);
2615-
git_reference_free(current);
2616-
git_reference_free(new_head);
2617-
return error;
2618-
}
2619-
26202621
int git_repository_set_head_detached(
26212622
git_repository* repo,
26222623
const git_oid* commitish)

tests/repo/head.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,15 +261,17 @@ void test_repo_head__setting_head_updates_reflog(void)
261261
cl_git_pass(git_revparse_single(&tag, repo, "tags/test"));
262262
cl_git_pass(git_repository_set_head_detached(repo, git_object_id(tag)));
263263
cl_git_pass(git_repository_set_head(repo, "refs/heads/haacked"));
264+
cl_git_pass(git_repository_set_head(repo, "refs/tags/test"));
264265

265-
test_reflog(repo, 2, NULL, "refs/heads/haacked", "foo@example.com", "checkout: moving from master to haacked");
266-
test_reflog(repo, 1, NULL, "tags/test^{commit}", "foo@example.com", "checkout: moving from unborn to e90810b8df3e80c413d903f631643c716887138d");
267-
test_reflog(repo, 0, "tags/test^{commit}", "refs/heads/haacked", "foo@example.com", "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked");
266+
test_reflog(repo, 3, NULL, "refs/heads/haacked", "foo@example.com", "checkout: moving from master to haacked");
267+
test_reflog(repo, 2, NULL, "tags/test^{commit}", "foo@example.com", "checkout: moving from unborn to e90810b8df3e80c413d903f631643c716887138d");
268+
test_reflog(repo, 1, "tags/test^{commit}", "refs/heads/haacked", "foo@example.com", "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked");
269+
test_reflog(repo, 0, "refs/heads/haacked", "tags/test^{commit}", "foo@example.com", "checkout: moving from haacked to test");
268270

269271
cl_git_pass(git_annotated_commit_from_revspec(&annotated, repo, "haacked~0"));
270272
cl_git_pass(git_repository_set_head_detached_from_annotated(repo, annotated));
271273

272-
test_reflog(repo, 0, NULL, "refs/heads/haacked", "foo@example.com", "checkout: moving from haacked to haacked~0");
274+
test_reflog(repo, 0, NULL, "refs/heads/haacked", "foo@example.com", "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked~0");
273275

274276
git_annotated_commit_free(annotated);
275277
git_object_free(tag);

0 commit comments

Comments
 (0)