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

Commit 024d34c

Browse files
torvaldsgitster
authored andcommitted
request-pull: more strictly match local/remote branches
The current 'request-pull' will try to find matching commit on the given remote, and rewrite the "please pull" line to match that remote ref. That may be very helpful if your local tree doesn't match the layout of the remote branches, but for the common case it's been a recurring disaster, when "request-pull" is done against a delayed remote update, and it rewrites the target branch randomly to some other branch name that happens to have the same expected SHA1 (or more commonly, leaves it blank). To avoid that recurring problem, this changes "git request-pull" so that it matches the ref name to be pulled against the *local* repository, and then warns if the remote repository does not have that exact same branch or tag name and content. This means that git request-pull will never rewrite the ref-name you gave it. If the local branch name is "xyzzy", that is the only branch name that request-pull will ask the other side to fetch. If the remote has that branch under a different name, that's your problem and git request-pull will not try to fix it up (but git request-pull will warn about the fact that no exact matching branch is found, and you can edit the end result to then have the remote name you want if it doesn't match your local one). The new "find local ref" code will also complain loudly if you give an ambiguous refname (eg you have both a tag and a branch with that same name, and you don't specify "heads/name" or "tags/name"). Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b594c97 commit 024d34c

File tree

1 file changed

+43
-67
lines changed

1 file changed

+43
-67
lines changed

git-request-pull.sh

Lines changed: 43 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,7 @@ do
3535
shift
3636
done
3737

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

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

@@ -58,55 +45,68 @@ then
5845
die "fatal: Not a valid revision: $base"
5946
fi
6047

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

72+
prettyhead=${head#refs/}
73+
prettyhead=${prettyhead#heads/}
74+
6775
merge_base=$(git merge-base $baserev $headrev) ||
6876
die "fatal: No commits in common between $base and $head"
6977

70-
# $head is the token given from the command line, and $tag_name, if
71-
# exists, is the tag we are going to show the commit information for.
72-
# If that tag exists at the remote and it points at the commit, use it.
73-
# Otherwise, if a branch with the same name as $head exists at the remote
74-
# and their values match, use that instead.
78+
# $head is the refname from the command line.
79+
# If a ref with the same name as $head exists at the remote
80+
# and their values match, use that.
7581
#
7682
# Otherwise find a random ref that matches $headrev.
7783
find_matching_ref='
78-
sub abbr {
79-
my $ref = shift;
80-
if ($ref =~ s|^refs/heads/|| || $ref =~ s|^refs/tags/|tags/|) {
81-
return $ref;
82-
} else {
83-
return $ref;
84-
}
85-
}
86-
87-
my ($tagged, $branch, $found);
84+
my ($exact,$found);
8885
while (<STDIN>) {
89-
my ($sha1, $ref, $deref) = /^(\S+)\s+(\S+?)(\^\{\})?$/;
86+
my ($sha1, $ref, $deref) = /^(\S+)\s+([^^]+)(\S*)$/;
9087
next unless ($sha1 eq $ARGV[1]);
91-
$found = abbr($ref);
92-
if ($deref && $ref eq "tags/$ARGV[2]") {
93-
$tagged = $found;
94-
last;
88+
if ($ref eq $ARGV[0]) {
89+
$exact = $ref;
9590
}
96-
if ($ref =~ m|/\Q$ARGV[0]\E$|) {
97-
$exact = $found;
91+
if ($sha1 eq $ARGV[0]) {
92+
$found = $sha1;
9893
}
9994
}
100-
if ($tagged) {
101-
print "$tagged\n";
102-
} elsif ($exact) {
95+
if ($exact) {
10396
print "$exact\n";
10497
} elsif ($found) {
10598
print "$found\n";
10699
}
107100
'
108101

109-
ref=$(git ls-remote "$url" | @@PERL@@ -e "$find_matching_ref" "$head" "$headrev" "$tag_name")
102+
ref=$(git ls-remote "$url" | @@PERL@@ -e "$find_matching_ref" "$head" "$headrev")
103+
104+
if test -z "$ref"
105+
then
106+
echo "warn: No match for $prettyhead found at $url" >&2
107+
echo "warn: Are you sure you pushed '$prettyhead' there?" >&2
108+
status=1
109+
fi
110110

111111
url=$(git ls-remote --get-url "$url")
112112

@@ -116,7 +116,7 @@ git show -s --format='The following changes since commit %H:
116116
117117
are available in the git repository at:
118118
' $merge_base &&
119-
echo " $url${ref+ $ref}" &&
119+
echo " $url $prettyhead" &&
120120
git show -s --format='
121121
for you to fetch changes up to %H:
122122
@@ -129,34 +129,10 @@ then
129129
echo "(from the branch description for $branch_name local branch)"
130130
echo
131131
git config "branch.$branch_name.description"
132-
fi &&
133-
134-
if test -n "$tag_name"
135-
then
136-
if test -z "$ref" || test "$ref" != "tags/$tag_name"
137-
then
138-
echo >&2 "warn: You locally have $tag_name but it does not (yet)"
139-
echo >&2 "warn: appear to be at $url"
140-
echo >&2 "warn: Do you want to push it there, perhaps?"
141-
fi
142-
git cat-file tag "$tag_name" |
143-
sed -n -e '1,/^$/d' -e '/^-----BEGIN PGP /q' -e p
144-
echo
145-
fi &&
146-
147-
if test -n "$branch_name" || test -n "$tag_name"
148-
then
149132
echo "----------------------------------------------------------------"
150133
fi &&
151134

152135
git shortlog ^$baserev $headrev &&
153136
git diff -M --stat --summary $patch $merge_base..$headrev || status=1
154137

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

0 commit comments

Comments
 (0)