Skip to content

Commit adfe5d0

Browse files
peffgitster
authored andcommitted
sha1_name: implement @{push} shorthand
In a triangular workflow, each branch may have two distinct points of interest: the @{upstream} that you normally pull from, and the destination that you normally push to. There isn't a shorthand for the latter, but it's useful to have. For instance, you may want to know which commits you haven't pushed yet: git log @{push}.. Or as a more complicated example, imagine that you normally pull changes from origin/master (which you set as your @{upstream}), and push changes to your own personal fork (e.g., as myfork/topic). You may push to your fork from multiple machines, requiring you to integrate the changes from the push destination, rather than upstream. With this patch, you can just do: git rebase @{push} rather than typing out the full name. The heavy lifting is all done by branch_get_push; here we just wire it up to the "@{push}" syntax. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 48c5847 commit adfe5d0

File tree

3 files changed

+101
-1
lines changed

3 files changed

+101
-1
lines changed

Documentation/revisions.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,31 @@ some output processing may assume ref names in UTF-8.
9898
`branch.<name>.merge`). A missing branchname defaults to the
9999
current one.
100100

101+
'<branchname>@\{push\}', e.g. 'master@\{push\}', '@\{push\}'::
102+
The suffix '@\{push}' reports the branch "where we would push to" if
103+
`git push` were run while `branchname` was checked out (or the current
104+
'HEAD' if no branchname is specified). Since our push destination is
105+
in a remote repository, of course, we report the local tracking branch
106+
that corresponds to that branch (i.e., something in 'refs/remotes/').
107+
+
108+
Here's an example to make it more clear:
109+
+
110+
------------------------------
111+
$ git config push.default current
112+
$ git config remote.pushdefault myfork
113+
$ git checkout -b mybranch origin/master
114+
115+
$ git rev-parse --symbolic-full-name @{upstream}
116+
refs/remotes/origin/master
117+
118+
$ git rev-parse --symbolic-full-name @{push}
119+
refs/remotes/myfork/mybranch
120+
------------------------------
121+
+
122+
Note in the example that we set up a triangular workflow, where we pull
123+
from one location and push to another. In a non-triangular workflow,
124+
'@\{push}' is the same as '@\{upstream}', and there is no need for it.
125+
101126
'<rev>{caret}', e.g. 'HEAD{caret}, v1.5.1{caret}0'::
102127
A suffix '{caret}' to a revision parameter means the first parent of
103128
that commit object. '{caret}<n>' means the <n>th parent (i.e.

sha1_name.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,12 @@ static inline int upstream_mark(const char *string, int len)
435435
return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
436436
}
437437

438+
static inline int push_mark(const char *string, int len)
439+
{
440+
const char *suffix[] = { "@{push}" };
441+
return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
442+
}
443+
438444
static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned lookup_flags);
439445
static int interpret_nth_prior_checkout(const char *name, int namelen, struct strbuf *buf);
440446

@@ -482,7 +488,8 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1,
482488
nth_prior = 1;
483489
continue;
484490
}
485-
if (!upstream_mark(str + at, len - at)) {
491+
if (!upstream_mark(str + at, len - at) &&
492+
!push_mark(str + at, len - at)) {
486493
reflog_len = (len-1) - (at+2);
487494
len = at;
488495
}
@@ -1145,6 +1152,11 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)
11451152
upstream_mark, branch_get_upstream);
11461153
if (len > 0)
11471154
return len;
1155+
1156+
len = interpret_branch_mark(name, namelen, at - name, buf,
1157+
push_mark, branch_get_push);
1158+
if (len > 0)
1159+
return len;
11481160
}
11491161

11501162
return -1;

t/t1514-rev-parse-push.sh

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/bin/sh
2+
3+
test_description='test <branch>@{push} syntax'
4+
. ./test-lib.sh
5+
6+
resolve () {
7+
echo "$2" >expect &&
8+
git rev-parse --symbolic-full-name "$1" >actual &&
9+
test_cmp expect actual
10+
}
11+
12+
test_expect_success 'setup' '
13+
git init --bare parent.git &&
14+
git init --bare other.git &&
15+
git remote add origin parent.git &&
16+
git remote add other other.git &&
17+
test_commit base &&
18+
git push origin HEAD &&
19+
git branch --set-upstream-to=origin/master master &&
20+
git branch --track topic origin/master &&
21+
git push origin topic &&
22+
git push other topic
23+
'
24+
25+
test_expect_success '@{push} with default=nothing' '
26+
test_config push.default nothing &&
27+
test_must_fail git rev-parse master@{push}
28+
'
29+
30+
test_expect_success '@{push} with default=simple' '
31+
test_config push.default simple &&
32+
resolve master@{push} refs/remotes/origin/master
33+
'
34+
35+
test_expect_success 'triangular @{push} fails with default=simple' '
36+
test_config push.default simple &&
37+
test_must_fail git rev-parse topic@{push}
38+
'
39+
40+
test_expect_success '@{push} with default=current' '
41+
test_config push.default current &&
42+
resolve topic@{push} refs/remotes/origin/topic
43+
'
44+
45+
test_expect_success '@{push} with default=matching' '
46+
test_config push.default matching &&
47+
resolve topic@{push} refs/remotes/origin/topic
48+
'
49+
50+
test_expect_success '@{push} with pushremote defined' '
51+
test_config push.default current &&
52+
test_config branch.topic.pushremote other &&
53+
resolve topic@{push} refs/remotes/other/topic
54+
'
55+
56+
test_expect_success '@{push} with push refspecs' '
57+
test_config push.default nothing &&
58+
test_config remote.origin.push refs/heads/*:refs/heads/magic/* &&
59+
git push &&
60+
resolve topic@{push} refs/remotes/origin/magic/topic
61+
'
62+
63+
test_done

0 commit comments

Comments
 (0)