Skip to content

Commit 498bcd3

Browse files
trastgitster
authored andcommitted
rev-list: fix --reverse interaction with --parents
--reverse did not interact well with --parents, as the included test case shows: in a history like A--B. \ \ `C--M--D the command git rev-list --reverse --parents --full-history HEAD erroneously lists D as having no parents at all. (Without --reverse, it correctly lists M.) This is caused by the machinery driving --reverse: it first grabs all commits through the normal routines, then runs them through the same routines again, effectively simplifying them twice. Fix this by moving the --reverse one level up, into get_revision(). This way we can cleanly grab all commits via the normal calls, then just pop them off the list one by one without interfering with get_revision_internal(). Signed-off-by: Thomas Rast <trast@student.ethz.ch> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 6534703 commit 498bcd3

File tree

3 files changed

+60
-21
lines changed

3 files changed

+60
-21
lines changed

revision.c

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1786,26 +1786,6 @@ static struct commit *get_revision_internal(struct rev_info *revs)
17861786
return c;
17871787
}
17881788

1789-
if (revs->reverse) {
1790-
int limit = -1;
1791-
1792-
if (0 <= revs->max_count) {
1793-
limit = revs->max_count;
1794-
if (0 < revs->skip_count)
1795-
limit += revs->skip_count;
1796-
}
1797-
l = NULL;
1798-
while ((c = get_revision_1(revs))) {
1799-
commit_list_insert(c, &l);
1800-
if ((0 < limit) && !--limit)
1801-
break;
1802-
}
1803-
revs->commits = l;
1804-
revs->reverse = 0;
1805-
revs->max_count = -1;
1806-
c = NULL;
1807-
}
1808-
18091789
/*
18101790
* Now pick up what they want to give us
18111791
*/
@@ -1878,7 +1858,23 @@ static struct commit *get_revision_internal(struct rev_info *revs)
18781858

18791859
struct commit *get_revision(struct rev_info *revs)
18801860
{
1881-
struct commit *c = get_revision_internal(revs);
1861+
struct commit *c;
1862+
struct commit_list *reversed;
1863+
1864+
if (revs->reverse) {
1865+
reversed = NULL;
1866+
while ((c = get_revision_internal(revs))) {
1867+
commit_list_insert(c, &reversed);
1868+
}
1869+
revs->commits = reversed;
1870+
revs->reverse = 0;
1871+
revs->reverse_output_stage = 1;
1872+
}
1873+
1874+
if (revs->reverse_output_stage)
1875+
return pop_commit(&revs->commits);
1876+
1877+
c = get_revision_internal(revs);
18821878
if (c && revs->graph)
18831879
graph_update(revs->graph, c);
18841880
return c;

revision.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ struct rev_info {
5353
rewrite_parents:1,
5454
print_parents:1,
5555
reverse:1,
56+
reverse_output_stage:1,
5657
cherry_pick:1,
5758
first_parent_only:1;
5859

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/bin/sh
2+
3+
test_description='--reverse combines with --parents'
4+
5+
. ./test-lib.sh
6+
7+
8+
commit () {
9+
test_tick &&
10+
echo $1 > foo &&
11+
git add foo &&
12+
git commit -m "$1"
13+
}
14+
15+
test_expect_success 'set up --reverse example' '
16+
commit one &&
17+
git tag root &&
18+
commit two &&
19+
git checkout -b side HEAD^ &&
20+
commit three &&
21+
git checkout master &&
22+
git merge -s ours side &&
23+
commit five
24+
'
25+
26+
test_expect_success '--reverse --parents --full-history combines correctly' '
27+
git rev-list --parents --full-history master -- foo |
28+
tac > expected &&
29+
git rev-list --reverse --parents --full-history master -- foo \
30+
> actual &&
31+
test_cmp actual expected
32+
'
33+
34+
test_expect_success '--boundary does too' '
35+
git rev-list --boundary --parents --full-history master ^root -- foo |
36+
tac > expected &&
37+
git rev-list --boundary --reverse --parents --full-history \
38+
master ^root -- foo > actual &&
39+
test_cmp actual expected
40+
'
41+
42+
test_done

0 commit comments

Comments
 (0)