encountered. Append `:track,nobracket` to show tracking
information without brackets (i.e "ahead N, behind M").
+
-Also respects `:remotename` to state the name of the *remote* instead of
-the ref.
+For any remote-tracking branch `%(upstream)`, `%(upstream:remotename)`
+and `%(upstream:remoteref)` refer to the name of the remote and the
+name of the tracked remote ref, respectively. In other words, the
+remote-tracking branch can be updated explicitly and individually by
+using the refspec `%(upstream:remoteref):%(upstream)` to fetch from
+`%(upstream:remotename)`.
+
Has no effect if the ref does not have tracking information associated
with it. All the options apart from `nobracket` are mutually exclusive,
push::
The name of a local ref which represents the `@{push}`
location for the displayed ref. Respects `:short`, `:lstrip`,
- `:rstrip`, `:track`, `:trackshort` and `:remotename` options as
- `upstream` does. Produces an empty string if no `@{push}` ref is
- configured.
+ `:rstrip`, `:track`, `:trackshort`, `:remotename`, and `:remoteref`
+ options as `upstream` does. Produces an empty string if no `@{push}`
+ ref is configured.
HEAD::
'*' if HEAD matches current ref (the checked out branch), ' '
struct align align;
struct {
enum {
- RR_REF, RR_TRACK, RR_TRACKSHORT, RR_REMOTE_NAME
+ RR_REF, RR_TRACK, RR_TRACKSHORT, RR_REMOTE_NAME, RR_REMOTE_REF
} option;
struct refname_atom refname;
unsigned int nobracket : 1, push : 1, push_remote : 1;
else if (!strcmp(s, "remotename")) {
atom->u.remote_ref.option = RR_REMOTE_NAME;
atom->u.remote_ref.push_remote = 1;
+ } else if (!strcmp(s, "remoteref")) {
+ atom->u.remote_ref.option = RR_REMOTE_REF;
+ atom->u.remote_ref.push_remote = 1;
} else {
atom->u.remote_ref.option = RR_REF;
refname_atom_parser_internal(&atom->u.remote_ref.refname,
*s = xstrdup(remote);
else
*s = "";
+ } else if (atom->u.remote_ref.option == RR_REMOTE_REF) {
+ int explicit;
+ const char *merge;
+
+ merge = remote_ref_for_branch(branch, atom->u.remote_ref.push,
+ &explicit);
+ if (explicit)
+ *s = xstrdup(merge);
+ else
+ *s = "";
} else
die("BUG: unhandled RR_* enum");
}
return remote_for_branch(branch, explicit);
}
+const char *remote_ref_for_branch(struct branch *branch, int for_push,
+ int *explicit)
+{
+ if (branch) {
+ if (!for_push) {
+ if (branch->merge_nr) {
+ if (explicit)
+ *explicit = 1;
+ return branch->merge_name[0];
+ }
+ } else {
+ const char *dst, *remote_name =
+ pushremote_for_branch(branch, NULL);
+ struct remote *remote = remote_get(remote_name);
+
+ if (remote && remote->push_refspec_nr &&
+ (dst = apply_refspecs(remote->push,
+ remote->push_refspec_nr,
+ branch->refname))) {
+ if (explicit)
+ *explicit = 1;
+ return dst;
+ }
+ }
+ }
+ if (explicit)
+ *explicit = 0;
+ return "";
+}
+
static struct remote *remote_get_1(const char *name,
const char *(*get_default)(struct branch *, int *))
{
struct branch *branch_get(const char *name);
const char *remote_for_branch(struct branch *branch, int *explicit);
const char *pushremote_for_branch(struct branch *branch, int *explicit);
+const char *remote_ref_for_branch(struct branch *branch, int for_push,
+ int *explicit);
int branch_has_merge_config(struct branch *branch);
int branch_merge_matches(struct branch *, int n, const char *);