Skip to content

Commit 923c0f7

Browse files
committed
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 parent c31032a commit 923c0f7

File tree

2 files changed

+50
-21
lines changed

2 files changed

+50
-21
lines changed

src/clone.c

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -162,16 +162,45 @@ static int update_head_to_default(git_repository *repo)
162162
return error;
163163
}
164164

165+
static int update_remote_head_byname(
166+
git_repository *repo,
167+
const char *remote_name,
168+
const char *tracking_branch_name,
169+
const char *reflog_message)
170+
{
171+
git_buf tracking_head_name = GIT_BUF_INIT;
172+
git_reference *remote_head = NULL;
173+
int error;
174+
175+
if ((error = git_buf_printf(&tracking_head_name,
176+
"%s%s/%s",
177+
GIT_REFS_REMOTES_DIR,
178+
remote_name,
179+
GIT_HEAD_FILE)) < 0)
180+
goto cleanup;
181+
182+
error = git_reference_symbolic_create(
183+
&remote_head,
184+
repo,
185+
git_buf_cstr(&tracking_head_name),
186+
tracking_branch_name,
187+
true,
188+
reflog_message);
189+
190+
cleanup:
191+
git_reference_free(remote_head);
192+
git_buf_dispose(&tracking_head_name);
193+
return error;
194+
}
195+
165196
static int update_remote_head(
166197
git_repository *repo,
167198
git_remote *remote,
168199
git_buf *target,
169200
const char *reflog_message)
170201
{
171202
git_refspec *refspec;
172-
git_reference *remote_head = NULL;
173-
git_buf remote_head_name = GIT_BUF_INIT;
174-
git_buf remote_branch_name = GIT_BUF_INIT;
203+
git_buf tracking_branch_name = GIT_BUF_INIT;
175204
int error;
176205

177206
/* Determine the remote tracking ref name from the local branch */
@@ -184,30 +213,19 @@ static int update_remote_head(
184213
}
185214

186215
if ((error = git_refspec_transform(
187-
&remote_branch_name,
216+
&tracking_branch_name,
188217
refspec,
189218
git_buf_cstr(target))) < 0)
190219
goto cleanup;
191220

192-
if ((error = git_buf_printf(&remote_head_name,
193-
"%s%s/%s",
194-
GIT_REFS_REMOTES_DIR,
195-
git_remote_name(remote),
196-
GIT_HEAD_FILE)) < 0)
197-
goto cleanup;
198-
199-
error = git_reference_symbolic_create(
200-
&remote_head,
221+
error = update_remote_head_byname(
201222
repo,
202-
git_buf_cstr(&remote_head_name),
203-
git_buf_cstr(&remote_branch_name),
204-
true,
223+
git_remote_name(remote),
224+
git_buf_cstr(&tracking_branch_name),
205225
reflog_message);
206226

207227
cleanup:
208-
git_reference_free(remote_head);
209-
git_buf_dispose(&remote_branch_name);
210-
git_buf_dispose(&remote_head_name);
228+
git_buf_dispose(&tracking_branch_name);
211229
return error;
212230
}
213231

@@ -277,8 +295,11 @@ static int update_head_to_branch(
277295
if ((retcode = git_reference_lookup(&remote_ref, repo, git_buf_cstr(&remote_branch_name))) < 0)
278296
goto cleanup;
279297

280-
retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch,
281-
reflog_message);
298+
if ((retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch,
299+
reflog_message)) < 0)
300+
goto cleanup;
301+
302+
retcode = update_remote_head_byname(repo, remote_name, remote_branch_name.ptr, reflog_message);
282303

283304
cleanup:
284305
git_reference_free(remote_ref);

tests/clone/nonetwork.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ void test_clone_nonetwork__can_prevent_the_checkout_of_a_standard_repo(void)
158158

159159
void test_clone_nonetwork__can_checkout_given_branch(void)
160160
{
161+
git_reference *remote_head;
162+
161163
g_options.checkout_branch = "test";
162164
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
163165

@@ -167,6 +169,12 @@ void test_clone_nonetwork__can_checkout_given_branch(void)
167169
cl_assert_equal_s(git_reference_name(g_ref), "refs/heads/test");
168170

169171
cl_assert(git_path_exists("foo/readme.txt"));
172+
173+
cl_git_pass(git_reference_lookup(&remote_head, g_repo, "refs/remotes/origin/HEAD"));
174+
cl_assert_equal_i(GIT_REFERENCE_SYMBOLIC, git_reference_type(remote_head));
175+
cl_assert_equal_s("refs/remotes/origin/test", git_reference_symbolic_target(remote_head));
176+
177+
git_reference_free(remote_head);
170178
}
171179

172180
static int clone_cancel_fetch_transfer_progress_cb(

0 commit comments

Comments
 (0)