Skip to content

Commit 2f6f10b

Browse files
authored
Merge pull request libgit2#5300 from tiennou/fix/branch-documentation
branch: clarify documentation around branches
2 parents d2d01f7 + 97b8491 commit 2f6f10b

File tree

6 files changed

+169
-92
lines changed

6 files changed

+169
-92
lines changed

include/git2/branch.h

Lines changed: 74 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ GIT_EXTERN(int) git_branch_create_from_annotated(
7575
/**
7676
* Delete an existing branch reference.
7777
*
78-
* If the branch is successfully deleted, the passed reference
79-
* object will be invalidated. The reference must be freed manually
80-
* by the user.
78+
* Note that if the deletion succeeds, the reference object will not
79+
* be valid anymore, and should be freed immediately by the user using
80+
* `git_reference_free()`.
8181
*
8282
* @param branch A valid reference representing a branch
8383
* @return 0 on success, or an error code.
@@ -126,6 +126,12 @@ GIT_EXTERN(void) git_branch_iterator_free(git_branch_iterator *iter);
126126
* The new branch name will be checked for validity.
127127
* See `git_tag_create()` for rules about valid names.
128128
*
129+
* Note that if the move succeeds, the old reference object will not
130+
+ be valid anymore, and should be freed immediately by the user using
131+
+ `git_reference_free()`.
132+
*
133+
* @param out New reference object for the updated name.
134+
*
129135
* @param branch Current underlying reference of the branch.
130136
*
131137
* @param new_branch_name Target name of the branch once the move
@@ -145,17 +151,14 @@ GIT_EXTERN(int) git_branch_move(
145151
* Lookup a branch by its name in a repository.
146152
*
147153
* The generated reference must be freed by the user.
148-
*
149154
* The branch name will be checked for validity.
150-
* See `git_tag_create()` for rules about valid names.
151155
*
152-
* @param out pointer to the looked-up branch reference
156+
* @see git_tag_create for rules about valid names.
153157
*
158+
* @param out pointer to the looked-up branch reference
154159
* @param repo the repository to look up the branch
155-
*
156160
* @param branch_name Name of the branch to be looked-up;
157161
* this name is validated for consistency.
158-
*
159162
* @param branch_type Type of the considered branch. This should
160163
* be valued with either GIT_BRANCH_LOCAL or GIT_BRANCH_REMOTE.
161164
*
@@ -169,116 +172,130 @@ GIT_EXTERN(int) git_branch_lookup(
169172
git_branch_t branch_type);
170173

171174
/**
172-
* Return the name of the given local or remote branch.
175+
* Get the branch name
176+
*
177+
* Given a reference object, this will check that it really is a branch (ie.
178+
* it lives under "refs/heads/" or "refs/remotes/"), and return the branch part
179+
* of it.
173180
*
174-
* The name of the branch matches the definition of the name
175-
* for git_branch_lookup. That is, if the returned name is given
176-
* to git_branch_lookup() then the reference is returned that
177-
* was given to this function.
181+
* @param out Pointer to the abbreviated reference name.
182+
* Owned by ref, do not free.
178183
*
179-
* @param out where the pointer of branch name is stored;
180-
* this is valid as long as the ref is not freed.
181-
* @param ref the reference ideally pointing to a branch
184+
* @param ref A reference object, ideally pointing to a branch
182185
*
183-
* @return 0 on success; otherwise an error code (e.g., if the
184-
* ref is no local or remote branch).
186+
* @return 0 on success; GIT_EINVALID if the reference isn't either a local or
187+
* remote branch, otherwise an error code.
185188
*/
186189
GIT_EXTERN(int) git_branch_name(
187190
const char **out,
188191
const git_reference *ref);
189192

190193
/**
191-
* Return the reference supporting the remote tracking branch,
192-
* given a local branch reference.
194+
* Get the upstream of a branch
193195
*
194-
* @param out Pointer where to store the retrieved
195-
* reference.
196+
* Given a reference, this will return a new reference object corresponding
197+
* to its remote tracking branch. The reference must be a local branch.
196198
*
199+
* @see git_branch_upstream_name for details on the resolution.
200+
*
201+
* @param out Pointer where to store the retrieved reference.
197202
* @param branch Current underlying reference of the branch.
198203
*
199204
* @return 0 on success; GIT_ENOTFOUND when no remote tracking
200-
* reference exists, otherwise an error code.
205+
* reference exists, otherwise an error code.
201206
*/
202207
GIT_EXTERN(int) git_branch_upstream(
203208
git_reference **out,
204209
const git_reference *branch);
205210

206211
/**
207-
* Set the upstream configuration for a given local branch
212+
* Set a branch's upstream branch
208213
*
209-
* @param branch the branch to configure
214+
* This will update the configuration to set the branch named `name` as the upstream of `branch`.
215+
* Pass a NULL name to unset the upstream information.
210216
*
211-
* @param upstream_name remote-tracking or local branch to set as
212-
* upstream. Pass NULL to unset.
217+
* @note the actual tracking reference must have been already created for the
218+
* operation to succeed.
213219
*
214-
* @return 0 or an error code
220+
* @param branch the branch to configure
221+
* @param branch_name remote-tracking or local branch to set as upstream.
222+
*
223+
* @return 0 on success; GIT_ENOTFOUND if there's no branch named `branch_name`
224+
* or an error code
215225
*/
216-
GIT_EXTERN(int) git_branch_set_upstream(git_reference *branch, const char *upstream_name);
226+
GIT_EXTERN(int) git_branch_set_upstream(
227+
git_reference *branch,
228+
const char *branch_name);
217229

218230
/**
219-
* Return the name of the reference supporting the remote tracking branch,
220-
* given the name of a local branch reference.
221-
*
222-
* @param out Pointer to the user-allocated git_buf which will be
223-
* filled with the name of the reference.
231+
* Get the upstream name of a branch
224232
*
225-
* @param repo the repository where the branches live
233+
* Given a local branch, this will return its remote-tracking branch information,
234+
* as a full reference name, ie. "feature/nice" would become
235+
* "refs/remote/origin/feature/nice", depending on that branch's configuration.
226236
*
237+
* @param out the buffer into which the name will be written.
238+
* @param repo the repository where the branches live.
227239
* @param refname reference name of the local branch.
228240
*
229-
* @return 0, GIT_ENOTFOUND when no remote tracking reference exists,
230-
* otherwise an error code.
241+
* @return 0 on success, GIT_ENOTFOUND when no remote tracking reference exists,
242+
* or an error code.
231243
*/
232244
GIT_EXTERN(int) git_branch_upstream_name(
233245
git_buf *out,
234246
git_repository *repo,
235247
const char *refname);
236248

237249
/**
238-
* Determine if the current local branch is pointed at by HEAD.
250+
* Determine if HEAD points to the given branch
239251
*
240-
* @param branch Current underlying reference of the branch.
252+
* @param branch A reference to a local branch.
241253
*
242-
* @return 1 if HEAD points at the branch, 0 if it isn't,
243-
* error code otherwise.
254+
* @return 1 if HEAD points at the branch, 0 if it isn't, or a negative value
255+
* as an error code.
244256
*/
245257
GIT_EXTERN(int) git_branch_is_head(
246258
const git_reference *branch);
247259

248260
/**
249-
* Determine if the current branch is checked out in any linked
250-
* repository.
261+
* Determine if any HEAD points to the current branch
251262
*
252-
* @param branch Reference to the branch.
263+
* This will iterate over all known linked repositories (usually in the form of
264+
* worktrees) and report whether any HEAD is pointing at the current branch.
253265
*
254-
* @return 1 if branch is checked out, 0 if it isn't,
255-
* error code otherwise.
266+
* @param branch A reference to a local branch.
267+
*
268+
* @return 1 if branch is checked out, 0 if it isn't, an error code otherwise.
256269
*/
257270
GIT_EXTERN(int) git_branch_is_checked_out(
258271
const git_reference *branch);
259272

260273
/**
261-
* Return the name of remote that the remote tracking branch belongs to.
274+
* Find the remote name of a remote-tracking branch
262275
*
263-
* @param out Pointer to the user-allocated git_buf which will be filled with the name of the remote.
276+
* This will return the name of the remote whose fetch refspec is matching
277+
* the given branch. E.g. given a branch "refs/remotes/test/master", it will
278+
* extract the "test" part. If refspecs from multiple remotes match,
279+
* the function will return GIT_EAMBIGUOUS.
264280
*
281+
* @param out The buffer into which the name will be written.
265282
* @param repo The repository where the branch lives.
283+
* @param refname complete name of the remote tracking branch.
266284
*
267-
* @param canonical_branch_name name of the remote tracking branch.
268-
*
269-
* @return 0, GIT_ENOTFOUND
270-
* when no remote matching remote was found,
271-
* GIT_EAMBIGUOUS when the branch maps to several remotes,
272-
* otherwise an error code.
285+
* @return 0 on success, GIT_ENOTFOUND when no matching remote was found,
286+
* GIT_EAMBIGUOUS when the branch maps to several remotes,
287+
* otherwise an error code.
273288
*/
274289
GIT_EXTERN(int) git_branch_remote_name(
275290
git_buf *out,
276291
git_repository *repo,
277-
const char *canonical_branch_name);
278-
292+
const char *refname);
279293

280294
/**
281-
* Retrieve the name of the upstream remote of a local branch
295+
* Retrieve the upstream remote of a local branch
296+
*
297+
* This will return the currently configured "branch.*.remote" for a given
298+
* branch. This branch must be local.
282299
*
283300
* @param buf the buffer into which to write the name
284301
* @param repo the repository in which to look

src/branch.c

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -597,35 +597,36 @@ static int unset_upstream(git_config *config, const char *shortname)
597597
return -1;
598598
}
599599

600-
int git_branch_set_upstream(git_reference *branch, const char *upstream_name)
600+
int git_branch_set_upstream(git_reference *branch, const char *branch_name)
601601
{
602-
git_buf key = GIT_BUF_INIT, value = GIT_BUF_INIT;
602+
git_buf key = GIT_BUF_INIT, remote_name = GIT_BUF_INIT, merge_refspec = GIT_BUF_INIT;
603603
git_reference *upstream;
604604
git_repository *repo;
605605
git_remote *remote = NULL;
606606
git_config *config;
607-
const char *name, *shortname;
607+
const char *refname, *shortname;
608608
int local, error;
609609
const git_refspec *fetchspec;
610610

611-
name = git_reference_name(branch);
612-
if (!git_reference__is_branch(name))
613-
return not_a_local_branch(name);
611+
refname = git_reference_name(branch);
612+
if (!git_reference__is_branch(refname))
613+
return not_a_local_branch(refname);
614614

615615
if (git_repository_config__weakptr(&config, git_reference_owner(branch)) < 0)
616616
return -1;
617617

618-
shortname = name + strlen(GIT_REFS_HEADS_DIR);
618+
shortname = refname + strlen(GIT_REFS_HEADS_DIR);
619619

620-
if (upstream_name == NULL)
620+
/* We're unsetting, delegate and bail-out */
621+
if (branch_name == NULL)
621622
return unset_upstream(config, shortname);
622623

623624
repo = git_reference_owner(branch);
624625

625-
/* First we need to figure out whether it's a branch or remote-tracking */
626-
if (git_branch_lookup(&upstream, repo, upstream_name, GIT_BRANCH_LOCAL) == 0)
626+
/* First we need to resolve name to a branch */
627+
if (git_branch_lookup(&upstream, repo, branch_name, GIT_BRANCH_LOCAL) == 0)
627628
local = 1;
628-
else if (git_branch_lookup(&upstream, repo, upstream_name, GIT_BRANCH_REMOTE) == 0)
629+
else if (git_branch_lookup(&upstream, repo, branch_name, GIT_BRANCH_REMOTE) == 0)
629630
local = 0;
630631
else {
631632
git_error_set(GIT_ERROR_REFERENCE,
@@ -634,60 +635,63 @@ int git_branch_set_upstream(git_reference *branch, const char *upstream_name)
634635
}
635636

636637
/*
637-
* If it's local, the remote is "." and the branch name is
638-
* simply the refname. Otherwise we need to figure out what
639-
* the remote-tracking branch's name on the remote is and use
640-
* that.
638+
* If it's a local-tracking branch, its remote is "." (as "the local
639+
* repository"), and the branch name is simply the refname.
640+
* Otherwise we need to figure out what the remote-tracking branch's
641+
* name on the remote is and use that.
641642
*/
642643
if (local)
643-
error = git_buf_puts(&value, ".");
644+
error = git_buf_puts(&remote_name, ".");
644645
else
645-
error = git_branch_remote_name(&value, repo, git_reference_name(upstream));
646+
error = git_branch_remote_name(&remote_name, repo, git_reference_name(upstream));
646647

647648
if (error < 0)
648649
goto on_error;
649650

651+
/* Update the upsteam branch config with the new name */
650652
if (git_buf_printf(&key, "branch.%s.remote", shortname) < 0)
651653
goto on_error;
652654

653-
if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&value)) < 0)
655+
if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&remote_name)) < 0)
654656
goto on_error;
655657

656658
if (local) {
657-
git_buf_clear(&value);
658-
if (git_buf_puts(&value, git_reference_name(upstream)) < 0)
659+
/* A local branch uses the upstream refname directly */
660+
if (git_buf_puts(&merge_refspec, git_reference_name(upstream)) < 0)
659661
goto on_error;
660662
} else {
661-
/* Get the remoe-tracking branch's refname in its repo */
662-
if (git_remote_lookup(&remote, repo, git_buf_cstr(&value)) < 0)
663+
/* We transform the upstream branch name according to the remote's refspecs */
664+
if (git_remote_lookup(&remote, repo, git_buf_cstr(&remote_name)) < 0)
663665
goto on_error;
664666

665667
fetchspec = git_remote__matching_dst_refspec(remote, git_reference_name(upstream));
666-
git_buf_clear(&value);
667-
if (!fetchspec || git_refspec_rtransform(&value, fetchspec, git_reference_name(upstream)) < 0)
668+
if (!fetchspec || git_refspec_rtransform(&merge_refspec, fetchspec, git_reference_name(upstream)) < 0)
668669
goto on_error;
669670

670671
git_remote_free(remote);
671672
remote = NULL;
672673
}
673674

675+
/* Update the merge branch config with the refspec */
674676
git_buf_clear(&key);
675677
if (git_buf_printf(&key, "branch.%s.merge", shortname) < 0)
676678
goto on_error;
677679

678-
if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&value)) < 0)
680+
if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&merge_refspec)) < 0)
679681
goto on_error;
680682

681683
git_reference_free(upstream);
682684
git_buf_dispose(&key);
683-
git_buf_dispose(&value);
685+
git_buf_dispose(&remote_name);
686+
git_buf_dispose(&merge_refspec);
684687

685688
return 0;
686689

687690
on_error:
688691
git_reference_free(upstream);
689692
git_buf_dispose(&key);
690-
git_buf_dispose(&value);
693+
git_buf_dispose(&remote_name);
694+
git_buf_dispose(&merge_refspec);
691695
git_remote_free(remote);
692696

693697
return -1;

src/refdb_fs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,7 +1502,7 @@ static int refdb_fs_backend__rename(
15021502
const char *message)
15031503
{
15041504
refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
1505-
git_reference *old, *new;
1505+
git_reference *old, *new = NULL;
15061506
git_filebuf file = GIT_FILEBUF_INIT;
15071507
int error;
15081508

@@ -1518,7 +1518,7 @@ static int refdb_fs_backend__rename(
15181518
return error;
15191519
}
15201520

1521-
new = git_reference__set_name(old, new_name);
1521+
new = git_reference__realloc(&old, new_name);
15221522
if (!new) {
15231523
git_reference_free(old);
15241524
return -1;

0 commit comments

Comments
 (0)