aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/git-for-each-ref.txt14
-rw-r--r--ref-filter.c15
-rw-r--r--remote.c30
-rw-r--r--remote.h2
4 files changed, 55 insertions, 6 deletions
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index 39f50bd53e..174af2c0ec 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -142,8 +142,12 @@ upstream::
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,
@@ -152,9 +156,9 @@ but if used together the last option is selected.
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), ' '
diff --git a/ref-filter.c b/ref-filter.c
index 4819707d03..2259563e73 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -77,7 +77,7 @@ static struct used_atom {
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;
@@ -164,6 +164,9 @@ static void remote_ref_atom_parser(const struct ref_format *format, struct used_
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,
@@ -1262,6 +1265,16 @@ static void fill_remote_ref_details(struct used_atom *atom, const char *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");
}
diff --git a/remote.c b/remote.c
index b220f0dfc6..2bdcfc280c 100644
--- a/remote.c
+++ b/remote.c
@@ -675,6 +675,36 @@ const char *pushremote_for_branch(struct branch *branch, int *explicit)
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 *))
{
diff --git a/remote.h b/remote.h
index 2ecf4c8c74..1f6611be21 100644
--- a/remote.h
+++ b/remote.h
@@ -223,6 +223,8 @@ struct branch {
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 *);