Skip to content

Commit 6a37d4c

Browse files
committed
Merge branch 'ps/shift-root-in-graph' into seen
In a history with more than one root commit, "git log --graph --oneline" stuffed an unrelated commit immediately below a root commit, which has been corrected by making the spot below a root unavailable. * ps/shift-root-in-graph: graph: add indentation for commits preceded by a root
2 parents a876b3b + d6e1ee4 commit 6a37d4c

2 files changed

Lines changed: 198 additions & 6 deletions

File tree

graph.c

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ struct column {
6060
* index into column_colors.
6161
*/
6262
unsigned short color;
63+
/*
64+
* A placeholder column keeps the column of the root filled for one
65+
* extra row, avoiding a next unrelated commit to be printed in the
66+
* same column. Placeholder columns don't propagate to the following
67+
* commit.
68+
*/
69+
unsigned is_placeholder:1;
6370
};
6471

6572
enum graph_state {
@@ -572,6 +579,7 @@ static void graph_insert_into_new_columns(struct git_graph *graph,
572579
i = graph->num_new_columns++;
573580
graph->new_columns[i].commit = commit;
574581
graph->new_columns[i].color = graph_find_commit_color(graph, commit);
582+
graph->new_columns[i].is_placeholder = 0;
575583
}
576584

577585
if (graph->num_parents > 1 && idx > -1 && graph->merge_layout == -1) {
@@ -616,7 +624,7 @@ static void graph_update_columns(struct git_graph *graph)
616624
{
617625
struct commit_list *parent;
618626
int max_new_columns;
619-
int i, seen_this, is_commit_in_columns;
627+
int i, seen_this, is_commit_in_columns, is_root;
620628

621629
/*
622630
* Swap graph->columns with graph->new_columns
@@ -663,6 +671,9 @@ static void graph_update_columns(struct git_graph *graph)
663671
*/
664672
seen_this = 0;
665673
is_commit_in_columns = 1;
674+
is_root = graph->num_parents == 0 &&
675+
!graph->commit->parents &&
676+
!(graph->commit->object.flags & BOUNDARY);
666677
for (i = 0; i <= graph->num_columns; i++) {
667678
struct commit *col_commit;
668679
if (i == graph->num_columns) {
@@ -697,11 +708,40 @@ static void graph_update_columns(struct git_graph *graph)
697708
* least 2, even if it has no interesting parents.
698709
* The current commit always takes up at least 2
699710
* spaces.
711+
*
712+
* Check for the commit to be a root, no parents
713+
* and that it is not a boundary commit. If so, add a
714+
* placeholder to keep that column filled for
715+
* at least one row.
716+
*
717+
* Prevents the next commit from being inserted
718+
* just below and making the graph confusing.
700719
*/
701-
if (graph->num_parents == 0)
720+
if (is_root) {
721+
graph_insert_into_new_columns(graph, graph->commit, i);
722+
graph->new_columns[graph->num_new_columns - 1]
723+
.is_placeholder = 1;
724+
} else if (graph->num_parents == 0) {
702725
graph->width += 2;
726+
}
703727
} else {
704-
graph_insert_into_new_columns(graph, col_commit, -1);
728+
if (graph->columns[i].is_placeholder) {
729+
/*
730+
* Keep the placeholders if the next commit is
731+
* a root also, making the indentation cascade.
732+
*/
733+
if (!seen_this && is_root) {
734+
graph_insert_into_new_columns(graph,
735+
graph->columns[i].commit, i);
736+
graph->new_columns[graph->num_new_columns - 1]
737+
.is_placeholder = 1;
738+
} else if (!seen_this) {
739+
graph->mapping[graph->width] = -1;
740+
graph->width += 2;
741+
}
742+
} else {
743+
graph_insert_into_new_columns(graph, col_commit, -1);
744+
}
705745
}
706746
}
707747

@@ -872,7 +912,10 @@ static void graph_output_padding_line(struct git_graph *graph,
872912
graph_line_addstr(line, "~ ");
873913
break;
874914
}
875-
graph_line_write_column(line, &graph->new_columns[i], '|');
915+
if (graph->new_columns[i].is_placeholder)
916+
graph_line_write_column(line, &graph->new_columns[i], ' ');
917+
else
918+
graph_line_write_column(line, &graph->new_columns[i], '|');
876919
graph_line_addch(line, ' ');
877920
}
878921
}
@@ -1106,7 +1149,13 @@ static void graph_output_commit_line(struct git_graph *graph, struct graph_line
11061149
graph->mapping[2 * i] < i) {
11071150
graph_line_write_column(line, col, '/');
11081151
} else {
1109-
graph_line_write_column(line, col, '|');
1152+
if (col->is_placeholder) {
1153+
if (seen_this)
1154+
continue;
1155+
graph_line_write_column(line, col, ' ');
1156+
} else {
1157+
graph_line_write_column(line, col, '|');
1158+
}
11101159
}
11111160
graph_line_addch(line, ' ');
11121161
}
@@ -1250,7 +1299,14 @@ static void graph_output_post_merge_line(struct git_graph *graph, struct graph_l
12501299
if (!graph_needs_truncation(graph, i + 1))
12511300
graph_line_addch(line, ' ');
12521301
} else {
1253-
graph_line_write_column(line, col, '|');
1302+
if (col->is_placeholder) {
1303+
if (seen_this)
1304+
continue;
1305+
graph_line_write_column(line, col, ' ');
1306+
} else {
1307+
graph_line_write_column(line, col, '|');
1308+
}
1309+
12541310
if (graph->merge_layout != 0 || i != graph->commit_index - 1) {
12551311
if (parent_col)
12561312
graph_line_write_column(

t/t4215-log-skewed-merges.sh

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,4 +514,140 @@ test_expect_success 'log --graph --graph-lane-limit=7 check if it shows all 3 pa
514514
EOF
515515
'
516516

517+
test_expect_success 'log --graph with root commit' '
518+
git checkout --orphan 8_a &&
519+
test_commit 8_A &&
520+
test_commit 8_A1 &&
521+
git checkout --orphan 8_b &&
522+
test_commit 8_B &&
523+
524+
check_graph 8_b 8_a <<-\EOF
525+
* 8_B
526+
* 8_A1
527+
/
528+
* 8_A
529+
EOF
530+
'
531+
532+
test_expect_success 'log --graph with multiple root commits' '
533+
test_commit 8_B1 &&
534+
git checkout --orphan 8_c &&
535+
test_commit 8_C &&
536+
537+
check_graph 8_c 8_b 8_a <<-\EOF
538+
* 8_C
539+
* 8_B1
540+
/
541+
* 8_B
542+
* 8_A1
543+
/
544+
* 8_A
545+
EOF
546+
'
547+
548+
test_expect_success 'log --graph commit from a two parent merge shifted' '
549+
git checkout --orphan 9_b &&
550+
test_commit 9_B &&
551+
git checkout --orphan 9_c &&
552+
test_commit 9_C &&
553+
git checkout 9_b &&
554+
git merge 9_c --allow-unrelated-histories -m 9_M &&
555+
git checkout --orphan 9_a &&
556+
test_commit 9_A &&
557+
test_commit 9_A1 &&
558+
test_commit 9_A2 &&
559+
560+
check_graph 9_a 9_b <<-\EOF
561+
* 9_A2
562+
* 9_A1
563+
* 9_A
564+
* 9_M
565+
/|
566+
| * 9_C
567+
* 9_B
568+
EOF
569+
'
570+
571+
test_expect_success 'log --graph commit from a three parent merge shifted' '
572+
git checkout --orphan 10_b &&
573+
test_commit 10_B &&
574+
git checkout --orphan 10_c &&
575+
test_commit 10_C &&
576+
git checkout --orphan 10_d &&
577+
test_commit 10_D &&
578+
git checkout 10_b &&
579+
TREE=$(git write-tree) &&
580+
MERGE=$(git commit-tree $TREE -p 10_b -p 10_c -p 10_d -m 10_M) &&
581+
git reset --hard $MERGE &&
582+
git checkout --orphan 10_a &&
583+
test_commit 10_A &&
584+
test_commit 10_A1 &&
585+
test_commit 10_A2 &&
586+
587+
check_graph 10_a 10_b <<-\EOF
588+
* 10_A2
589+
* 10_A1
590+
* 10_A
591+
* 10_M
592+
/|\
593+
| | * 10_D
594+
| * 10_C
595+
* 10_B
596+
EOF
597+
'
598+
599+
test_expect_success 'log --graph commit from a four parent merge shifted' '
600+
git checkout --orphan 11_b &&
601+
test_commit 11_B &&
602+
git checkout --orphan 11_c &&
603+
test_commit 11_C &&
604+
git checkout --orphan 11_d &&
605+
test_commit 11_D &&
606+
git checkout --orphan 11_e &&
607+
test_commit 11_E &&
608+
git checkout 11_b &&
609+
TREE=$(git write-tree) &&
610+
MERGE=$(git commit-tree $TREE -p 11_b -p 11_c -p 11_d -p 11_e -m 11_M) &&
611+
git reset --hard $MERGE &&
612+
git checkout --orphan 11_a &&
613+
test_commit 11_A &&
614+
test_commit 11_A1 &&
615+
test_commit 11_A2 &&
616+
617+
check_graph 11_a 11_b <<-\EOF
618+
* 11_A2
619+
* 11_A1
620+
* 11_A
621+
*-. 11_M
622+
/|\ \
623+
| | | * 11_E
624+
| | * 11_D
625+
| * 11_C
626+
* 11_B
627+
EOF
628+
'
629+
630+
test_expect_success 'log --graph disconnected three roots cascading' '
631+
git checkout --orphan 12_d &&
632+
test_commit 12_D &&
633+
test_commit 12_D1 &&
634+
git checkout --orphan 12_c &&
635+
test_commit 12_C &&
636+
git checkout --orphan 12_b &&
637+
test_commit 12_B &&
638+
git checkout --orphan 12_a &&
639+
test_commit 12_A &&
640+
641+
check_graph 12_a 12_b 12_c 12_d <<-\EOF
642+
* 12_A
643+
* 12_B
644+
* 12_C
645+
* 12_D1
646+
_ /
647+
/
648+
/
649+
* 12_D
650+
EOF
651+
'
652+
517653
test_done

0 commit comments

Comments
 (0)