Skip to content

Commit 003c84f

Browse files
committed
specifying ranges: we did not mean to make ".." an empty set
Either end of revision range operator can be omitted to default to HEAD, as in "origin.." (what did I do since I forked) or "..origin" (what did they do since I forked). But the current parser interprets ".." as an empty range "HEAD..HEAD", and worse yet, because ".." does exist on the filesystem, we get this annoying output: $ cd Documentation/howto $ git log .. ;# give me recent commits that touch Documentation/ area. fatal: ambiguous argument '..': both revision and filename Use '--' to separate filenames from revisions Surely we could say "git log ../" or even "git log -- .." to disambiguate, but we shouldn't have to. Helped-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent c142616 commit 003c84f

File tree

5 files changed

+56
-4
lines changed

5 files changed

+56
-4
lines changed

Documentation/revisions.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,13 @@ of 'r1' and 'r2' and is defined as
213213
It is the set of commits that are reachable from either one of
214214
'r1' or 'r2' but not from both.
215215

216+
In these two shorthands, you can omit one end and let it default to HEAD.
217+
For example, 'origin..' is a shorthand for 'origin..HEAD' and asks "What
218+
did I do since I forked from the origin branch?" Similarly, '..origin'
219+
is a shorthand for 'HEAD..origin' and asks "What did the origin do since
220+
I forked from them?" Note that '..' would mean 'HEAD..HEAD' which is an
221+
empty range that is both reachable and unreachable from HEAD.
222+
216223
Two other shorthands for naming a set that is formed by a commit
217224
and its parent commits exist. The 'r1{caret}@' notation means all
218225
parents of 'r1'. 'r1{caret}!' includes commit 'r1' but excludes

builtin/rev-parse.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ static int try_difference(const char *arg)
224224
const char *next;
225225
const char *this;
226226
int symmetric;
227+
static const char head_by_default[] = "HEAD";
227228

228229
if (!(dotdot = strstr(arg, "..")))
229230
return 0;
@@ -235,9 +236,20 @@ static int try_difference(const char *arg)
235236
next += symmetric;
236237

237238
if (!*next)
238-
next = "HEAD";
239+
next = head_by_default;
239240
if (dotdot == arg)
240-
this = "HEAD";
241+
this = head_by_default;
242+
243+
if (this == head_by_default && next == head_by_default &&
244+
!symmetric) {
245+
/*
246+
* Just ".."? That is not a range but the
247+
* pathspec for the parent directory.
248+
*/
249+
*dotdot = '.';
250+
return 0;
251+
}
252+
241253
if (!get_sha1(this, sha1) && !get_sha1(next, end)) {
242254
show_rev(NORMAL, end, next);
243255
show_rev(symmetric ? NORMAL : REVERSED, sha1, this);

revision.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,15 +1132,27 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs,
11321132
const char *this = arg;
11331133
int symmetric = *next == '.';
11341134
unsigned int flags_exclude = flags ^ UNINTERESTING;
1135+
static const char head_by_default[] = "HEAD";
11351136
unsigned int a_flags;
11361137

11371138
*dotdot = 0;
11381139
next += symmetric;
11391140

11401141
if (!*next)
1141-
next = "HEAD";
1142+
next = head_by_default;
11421143
if (dotdot == arg)
1143-
this = "HEAD";
1144+
this = head_by_default;
1145+
if (this == head_by_default && next == head_by_default &&
1146+
!symmetric) {
1147+
/*
1148+
* Just ".."? That is not a range but the
1149+
* pathspec for the parent directory.
1150+
*/
1151+
if (!cant_be_filename) {
1152+
*dotdot = '.';
1153+
return -1;
1154+
}
1155+
}
11441156
if (!get_sha1(this, from_sha1) &&
11451157
!get_sha1(next, sha1)) {
11461158
struct commit *a, *b;

t/t1506-rev-parse-diagnosis.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,4 +182,18 @@ test_expect_success '<commit>:file correctly diagnosed after a pathname' '
182182
test_cmp expect actual
183183
'
184184

185+
test_expect_success 'dotdot is not an empty set' '
186+
( H=$(git rev-parse HEAD) && echo $H && echo ^$H ) >expect &&
187+
188+
git rev-parse HEAD.. >actual &&
189+
test_cmp expect actual &&
190+
191+
git rev-parse ..HEAD >actual &&
192+
test_cmp expect actual &&
193+
194+
echo .. >expect &&
195+
git rev-parse .. >actual &&
196+
test_cmp expect actual
197+
'
198+
185199
test_done

t/t4202-log.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,4 +806,11 @@ test_expect_success 'log --graph with diff and stats' '
806806
test_cmp expect actual.sanitized
807807
'
808808

809+
test_expect_success 'dotdot is a parent directory' '
810+
mkdir -p a/b &&
811+
( echo sixth && echo fifth ) >expect &&
812+
( cd a/b && git log --format=%s .. ) >actual &&
813+
test_cmp expect actual
814+
'
815+
809816
test_done

0 commit comments

Comments
 (0)