Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Commit fe3623c

Browse files
committed
Merge branch 'lt/request-pull'
Discard the accumulated "heuristics" to guess from which branch the result wants to be pulled from and make sure what the end user specified is not second-guessed by "git request-pull", to avoid mistakes. * lt/request-pull: request-pull: documentation updates request-pull: resurrect "pretty refname" feature request-pull: test updates request-pull: pick up tag message as before request-pull: allow "local:remote" to specify names on both ends request-pull: more strictly match local/remote branches
2 parents 53d7d1b + ec44507 commit fe3623c

File tree

3 files changed

+126
-83
lines changed

3 files changed

+126
-83
lines changed

Documentation/git-request-pull.txt

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,65 @@ SYNOPSIS
1313
DESCRIPTION
1414
-----------
1515

16-
Summarizes the changes between two commits to the standard output, and includes
17-
the given URL in the generated summary.
16+
Generate a request asking your upstream project to pull changes into
17+
their tree. The request, printed to the standard output, summarizes
18+
the changes and indicates from where they can be pulled.
19+
20+
The upstream project is expected to have the commit named by
21+
`<start>` and the output asks it to integrate the changes you made
22+
since that commit, up to the commit named by `<end>`, by visiting
23+
the repository named by `<url>`.
24+
1825

1926
OPTIONS
2027
-------
2128
-p::
22-
Show patch text
29+
Include patch text in the output.
2330

2431
<start>::
25-
Commit to start at.
32+
Commit to start at. This names a commit that is already in
33+
the upstream history.
2634

2735
<url>::
28-
URL to include in the summary.
36+
The repository URL to be pulled from.
2937

3038
<end>::
31-
Commit to end at; defaults to HEAD.
39+
Commit to end at (defaults to HEAD). This names the commit
40+
at the tip of the history you are asking to be pulled.
41+
+
42+
When the repository named by `<url>` has the commit at a tip of a
43+
ref that is different from the ref you have locally, you can use the
44+
`<local>:<remote>` syntax, to have its local name, a colon `:`, and
45+
its remote name.
46+
47+
48+
EXAMPLE
49+
-------
50+
51+
Imagine that you built your work on your `master` branch on top of
52+
the `v1.0` release, and want it to be integrated to the project.
53+
First you push that change to your public repository for others to
54+
see:
55+
56+
git push https://git.ko.xz/project master
57+
58+
Then, you run this command:
59+
60+
git request-pull v1.0 https://git.ko.xz/project master
61+
62+
which will produce a request to the upstream, summarizing the
63+
changes between the `v1.0` release and your `master`, to pull it
64+
from your public repository.
65+
66+
If you pushed your change to a branch whose name is different from
67+
the one you have locally, e.g.
68+
69+
git push https://git.ko.xz/project master:for-linus
70+
71+
then you can ask that to be pulled with
72+
73+
git request-pull v1.0 https://git.ko.xz/project master:for-linus
74+
3275

3376
GIT
3477
---

git-request-pull.sh

Lines changed: 62 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,7 @@ do
3636
shift
3737
done
3838

39-
base=$1 url=$2 head=${3-HEAD} status=0 branch_name=
40-
41-
headref=$(git symbolic-ref -q "$head")
42-
if git show-ref -q --verify "$headref"
43-
then
44-
branch_name=${headref#refs/heads/}
45-
if test "z$branch_name" = "z$headref" ||
46-
! git config "branch.$branch_name.description" >/dev/null
47-
then
48-
branch_name=
49-
fi
50-
fi
51-
52-
tag_name=$(git describe --exact "$head^0" 2>/dev/null)
39+
base=$1 url=$2 status=0
5340

5441
test -n "$base" && test -n "$url" || usage
5542

@@ -59,55 +46,78 @@ then
5946
die "fatal: Not a valid revision: $base"
6047
fi
6148

49+
#
50+
# $3 must be a symbolic ref, a unique ref, or
51+
# a SHA object expression. It can also be of
52+
# the format 'local-name:remote-name'.
53+
#
54+
local=${3%:*}
55+
local=${local:-HEAD}
56+
remote=${3#*:}
57+
pretty_remote=${remote#refs/}
58+
pretty_remote=${pretty_remote#heads/}
59+
head=$(git symbolic-ref -q "$local")
60+
head=${head:-$(git show-ref --heads --tags "$local" | cut -d' ' -f2)}
61+
head=${head:-$(git rev-parse --quiet --verify "$local")}
62+
63+
# None of the above? Bad.
64+
test -z "$head" && die "fatal: Not a valid revision: $local"
65+
66+
# This also verifies that the resulting head is unique:
67+
# "git show-ref" could have shown multiple matching refs..
6268
headrev=$(git rev-parse --verify --quiet "$head"^0)
63-
if test -z "$headrev"
69+
test -z "$headrev" && die "fatal: Ambiguous revision: $local"
70+
71+
# Was it a branch with a description?
72+
branch_name=${head#refs/heads/}
73+
if test "z$branch_name" = "z$headref" ||
74+
! git config "branch.$branch_name.description" >/dev/null
6475
then
65-
die "fatal: Not a valid revision: $head"
76+
branch_name=
6677
fi
6778

6879
merge_base=$(git merge-base $baserev $headrev) ||
6980
die "fatal: No commits in common between $base and $head"
7081

71-
# $head is the token given from the command line, and $tag_name, if
72-
# exists, is the tag we are going to show the commit information for.
73-
# If that tag exists at the remote and it points at the commit, use it.
74-
# Otherwise, if a branch with the same name as $head exists at the remote
75-
# and their values match, use that instead.
82+
# $head is the refname from the command line.
83+
# If a ref with the same name as $head exists at the remote
84+
# and their values match, use that.
7685
#
7786
# Otherwise find a random ref that matches $headrev.
7887
find_matching_ref='
79-
sub abbr {
80-
my $ref = shift;
81-
if ($ref =~ s|^refs/heads/|| || $ref =~ s|^refs/tags/|tags/|) {
82-
return $ref;
83-
} else {
84-
return $ref;
85-
}
86-
}
88+
my ($head,$headrev) = (@ARGV);
89+
my ($found);
8790
88-
my ($tagged, $branch, $found);
8991
while (<STDIN>) {
90-
my ($sha1, $ref, $deref) = /^(\S+)\s+(\S+?)(\^\{\})?$/;
91-
next unless ($sha1 eq $ARGV[1]);
92-
$found = abbr($ref);
93-
if ($deref && $ref eq "tags/$ARGV[2]") {
94-
$tagged = $found;
95-
last;
92+
chomp;
93+
my ($sha1, $ref, $deref) = /^(\S+)\s+([^^]+)(\S*)$/;
94+
my ($pattern);
95+
next unless ($sha1 eq $headrev);
96+
97+
$pattern="/$head\$";
98+
if ($ref eq $head) {
99+
$found = $ref;
100+
}
101+
if ($ref =~ /$pattern/) {
102+
$found = $ref;
96103
}
97-
if ($ref =~ m|/\Q$ARGV[0]\E$|) {
98-
$exact = $found;
104+
if ($sha1 eq $head) {
105+
$found = $sha1;
99106
}
100107
}
101-
if ($tagged) {
102-
print "$tagged\n";
103-
} elsif ($exact) {
104-
print "$exact\n";
105-
} elsif ($found) {
108+
if ($found) {
106109
print "$found\n";
107110
}
108111
'
109112

110-
ref=$(git ls-remote "$url" | @@PERL@@ -e "$find_matching_ref" "$head" "$headrev" "$tag_name")
113+
ref=$(git ls-remote "$url" | @@PERL@@ -e "$find_matching_ref" "${remote:-HEAD}" "$headrev")
114+
115+
if test -z "$ref"
116+
then
117+
echo "warn: No match for commit $headrev found at $url" >&2
118+
echo "warn: Are you sure you pushed '${remote:-HEAD}' there?" >&2
119+
status=1
120+
fi
111121

112122
url=$(git ls-remote --get-url "$url")
113123

@@ -117,47 +127,31 @@ git show -s --format='The following changes since commit %H:
117127
118128
are available in the git repository at:
119129
' $merge_base &&
120-
echo " $url${ref+ $ref}" &&
130+
echo " $url $pretty_remote" &&
121131
git show -s --format='
122132
for you to fetch changes up to %H:
123133
124134
%s (%ci)
125135
126136
----------------------------------------------------------------' $headrev &&
127137

128-
if test -n "$branch_name"
138+
if test $(git cat-file -t "$head") = tag
129139
then
130-
echo "(from the branch description for $branch_name local branch)"
131-
echo
132-
git config "branch.$branch_name.description"
133-
fi &&
134-
135-
if test -n "$tag_name"
136-
then
137-
if test -z "$ref" || test "$ref" != "tags/$tag_name"
138-
then
139-
echo >&2 "warn: You locally have $tag_name but it does not (yet)"
140-
echo >&2 "warn: appear to be at $url"
141-
echo >&2 "warn: Do you want to push it there, perhaps?"
142-
fi
143-
git cat-file tag "$tag_name" |
140+
git cat-file tag "$head" |
144141
sed -n -e '1,/^$/d' -e '/^-----BEGIN PGP /q' -e p
145142
echo
143+
echo "----------------------------------------------------------------"
146144
fi &&
147145

148-
if test -n "$branch_name" || test -n "$tag_name"
146+
if test -n "$branch_name"
149147
then
148+
echo "(from the branch description for $branch_name local branch)"
149+
echo
150+
git config "branch.$branch_name.description"
150151
echo "----------------------------------------------------------------"
151152
fi &&
152153

153154
git shortlog ^$baserev $headrev &&
154155
git diff -M --stat --summary $patch $merge_base..$headrev || status=1
155156

156-
if test -z "$ref"
157-
then
158-
echo "warn: No branch of $url is at:" >&2
159-
git show -s --format='warn: %h: %s' $headrev >&2
160-
echo "warn: Are you sure you pushed '$head' there?" >&2
161-
status=1
162-
fi
163157
exit $status

t/t5150-request-pull.sh

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ test_expect_success 'setup: two scripts for reading pull requests' '
8686
s/[-0-9]\{10\} [:0-9]\{8\} [-+][0-9]\{4\}/DATE/g
8787
s/ [^ ].*/ SUBJECT/g
8888
s/ [^ ].* (DATE)/ SUBJECT (DATE)/g
89-
s/for-upstream/BRANCH/g
89+
s|tags/full|BRANCH|g
9090
s/mnemonic.txt/FILENAME/g
9191
s/^version [0-9]/VERSION/
9292
/^ FILENAME | *[0-9]* [-+]*\$/ b diffstat
@@ -127,7 +127,7 @@ test_expect_success 'pull request when forgot to push' '
127127
test_must_fail git request-pull initial "$downstream_url" \
128128
2>../err
129129
) &&
130-
grep "No branch of.*is at:\$" err &&
130+
grep "No match for commit .*" err &&
131131
grep "Are you sure you pushed" err
132132
133133
'
@@ -141,7 +141,7 @@ test_expect_success 'pull request after push' '
141141
git checkout initial &&
142142
git merge --ff-only master &&
143143
git push origin master:for-upstream &&
144-
git request-pull initial origin >../request
144+
git request-pull initial origin master:for-upstream >../request
145145
) &&
146146
sed -nf read-request.sed <request >digest &&
147147
cat digest &&
@@ -160,7 +160,7 @@ test_expect_success 'pull request after push' '
160160
161161
'
162162

163-
test_expect_success 'request names an appropriate branch' '
163+
test_expect_success 'request asks HEAD to be pulled' '
164164
165165
rm -fr downstream.git &&
166166
git init --bare downstream.git &&
@@ -179,7 +179,7 @@ test_expect_success 'request names an appropriate branch' '
179179
read repository &&
180180
read branch
181181
} <digest &&
182-
test "$branch" = tags/full
182+
test -z "$branch"
183183
184184
'
185185

@@ -212,12 +212,18 @@ test_expect_success 'pull request format' '
212212
cd local &&
213213
git checkout initial &&
214214
git merge --ff-only master &&
215-
git push origin master:for-upstream &&
216-
git request-pull initial "$downstream_url" >../request
215+
git push origin tags/full &&
216+
git request-pull initial "$downstream_url" tags/full >../request
217217
) &&
218218
<request sed -nf fuzz.sed >request.fuzzy &&
219-
test_i18ncmp expect request.fuzzy
219+
test_i18ncmp expect request.fuzzy &&
220220
221+
(
222+
cd local &&
223+
git request-pull initial "$downstream_url" tags/full:refs/tags/full
224+
) >request &&
225+
sed -nf fuzz.sed <request >request.fuzzy &&
226+
test_i18ncmp expect request.fuzzy
221227
'
222228

223229
test_expect_success 'request-pull ignores OPTIONS_KEEPDASHDASH poison' '
@@ -229,7 +235,7 @@ test_expect_success 'request-pull ignores OPTIONS_KEEPDASHDASH poison' '
229235
git checkout initial &&
230236
git merge --ff-only master &&
231237
git push origin master:for-upstream &&
232-
git request-pull -- initial "$downstream_url" >../request
238+
git request-pull -- initial "$downstream_url" master:for-upstream >../request
233239
)
234240
235241
'

0 commit comments

Comments
 (0)