clone: set refs/remotes/origin/HEAD when branch is specified When a branch is specified to check out in clone, update the remote tracking `HEAD` to point to it. This mimics git's behavior, when `git clone -b <name>` is used.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
diff --git a/src/clone.c b/src/clone.c
index 7ae90b0..6d5ebf6 100644
--- a/src/clone.c
+++ b/src/clone.c
@@ -162,6 +162,37 @@ done:
return error;
}
+static int update_remote_head_byname(
+ git_repository *repo,
+ const char *remote_name,
+ const char *tracking_branch_name,
+ const char *reflog_message)
+{
+ git_buf tracking_head_name = GIT_BUF_INIT;
+ git_reference *remote_head = NULL;
+ int error;
+
+ if ((error = git_buf_printf(&tracking_head_name,
+ "%s%s/%s",
+ GIT_REFS_REMOTES_DIR,
+ remote_name,
+ GIT_HEAD_FILE)) < 0)
+ goto cleanup;
+
+ error = git_reference_symbolic_create(
+ &remote_head,
+ repo,
+ git_buf_cstr(&tracking_head_name),
+ tracking_branch_name,
+ true,
+ reflog_message);
+
+cleanup:
+ git_reference_free(remote_head);
+ git_buf_dispose(&tracking_head_name);
+ return error;
+}
+
static int update_remote_head(
git_repository *repo,
git_remote *remote,
@@ -169,9 +200,7 @@ static int update_remote_head(
const char *reflog_message)
{
git_refspec *refspec;
- git_reference *remote_head = NULL;
- git_buf remote_head_name = GIT_BUF_INIT;
- git_buf remote_branch_name = GIT_BUF_INIT;
+ git_buf tracking_branch_name = GIT_BUF_INIT;
int error;
/* Determine the remote tracking ref name from the local branch */
@@ -184,30 +213,19 @@ static int update_remote_head(
}
if ((error = git_refspec_transform(
- &remote_branch_name,
+ &tracking_branch_name,
refspec,
git_buf_cstr(target))) < 0)
goto cleanup;
- if ((error = git_buf_printf(&remote_head_name,
- "%s%s/%s",
- GIT_REFS_REMOTES_DIR,
- git_remote_name(remote),
- GIT_HEAD_FILE)) < 0)
- goto cleanup;
-
- error = git_reference_symbolic_create(
- &remote_head,
+ error = update_remote_head_byname(
repo,
- git_buf_cstr(&remote_head_name),
- git_buf_cstr(&remote_branch_name),
- true,
+ git_remote_name(remote),
+ git_buf_cstr(&tracking_branch_name),
reflog_message);
cleanup:
- git_reference_free(remote_head);
- git_buf_dispose(&remote_branch_name);
- git_buf_dispose(&remote_head_name);
+ git_buf_dispose(&tracking_branch_name);
return error;
}
@@ -277,8 +295,11 @@ static int update_head_to_branch(
if ((retcode = git_reference_lookup(&remote_ref, repo, git_buf_cstr(&remote_branch_name))) < 0)
goto cleanup;
- retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch,
- reflog_message);
+ if ((retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch,
+ reflog_message)) < 0)
+ goto cleanup;
+
+ retcode = update_remote_head_byname(repo, remote_name, remote_branch_name.ptr, reflog_message);
cleanup:
git_reference_free(remote_ref);
diff --git a/tests/clone/nonetwork.c b/tests/clone/nonetwork.c
index 7ca4908..d4da3d3 100644
--- a/tests/clone/nonetwork.c
+++ b/tests/clone/nonetwork.c
@@ -158,6 +158,8 @@ void test_clone_nonetwork__can_prevent_the_checkout_of_a_standard_repo(void)
void test_clone_nonetwork__can_checkout_given_branch(void)
{
+ git_reference *remote_head;
+
g_options.checkout_branch = "test";
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
@@ -167,6 +169,12 @@ void test_clone_nonetwork__can_checkout_given_branch(void)
cl_assert_equal_s(git_reference_name(g_ref), "refs/heads/test");
cl_assert(git_path_exists("foo/readme.txt"));
+
+ cl_git_pass(git_reference_lookup(&remote_head, g_repo, "refs/remotes/origin/HEAD"));
+ cl_assert_equal_i(GIT_REFERENCE_SYMBOLIC, git_reference_type(remote_head));
+ cl_assert_equal_s("refs/remotes/origin/test", git_reference_symbolic_target(remote_head));
+
+ git_reference_free(remote_head);
}
static int clone_cancel_fetch_transfer_progress_cb(