Skip to content

Commit ff5ddca

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. Comments? * ps/shift-root-in-graph: SQUASH??? adjust tests for case challenged systems graph: add indentation for commits preceded by a root
2 parents f64e635 + b74d3d6 commit ff5ddca

File tree

2 files changed

+200
-6
lines changed

2 files changed

+200
-6
lines changed

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: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,4 +514,142 @@ 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 branch_8_a &&
519+
test_commit 8_A &&
520+
test_commit 8_A1 &&
521+
git checkout --orphan branch_8_b &&
522+
test_commit 8_B &&
523+
524+
check_graph branch_8_b branch_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 branch_8_c &&
535+
test_commit 8_C &&
536+
537+
check_graph branch_8_c branch_8_b branch_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 branch_9_b &&
550+
test_commit 9_B &&
551+
git checkout --orphan branch_9_c &&
552+
test_commit 9_C &&
553+
git checkout branch_9_b &&
554+
git merge branch_9_c --allow-unrelated-histories -m 9_M &&
555+
git checkout --orphan branch_9_a &&
556+
test_commit 9_A &&
557+
test_commit 9_A1 &&
558+
test_commit 9_A2 &&
559+
560+
check_graph branch_9_a branch_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 branch_10_b &&
573+
test_commit 10_B &&
574+
git checkout --orphan branch_10_c &&
575+
test_commit 10_C &&
576+
git checkout --orphan branch_10_d &&
577+
test_commit 10_D &&
578+
git checkout branch_10_b &&
579+
TREE=$(git write-tree) &&
580+
MERGE=$(git commit-tree $TREE \
581+
-p branch_10_b -p branch_10_c -p branch_10_d -m 10_M) &&
582+
git reset --hard $MERGE &&
583+
git checkout --orphan branch_10_a &&
584+
test_commit 10_A &&
585+
test_commit 10_A1 &&
586+
test_commit 10_A2 &&
587+
588+
check_graph branch_10_a branch_10_b <<-\EOF
589+
* 10_A2
590+
* 10_A1
591+
* 10_A
592+
* 10_M
593+
/|\
594+
| | * 10_D
595+
| * 10_C
596+
* 10_B
597+
EOF
598+
'
599+
600+
test_expect_success 'log --graph commit from a four parent merge shifted' '
601+
git checkout --orphan branch_11_b &&
602+
test_commit 11_B &&
603+
git checkout --orphan branch_11_c &&
604+
test_commit 11_C &&
605+
git checkout --orphan branch_11_d &&
606+
test_commit 11_D &&
607+
git checkout --orphan branch_11_e &&
608+
test_commit 11_E &&
609+
git checkout branch_11_b &&
610+
TREE=$(git write-tree) &&
611+
MERGE=$(git commit-tree $TREE \
612+
-p branch_11_b -p branch_11_c -p branch_11_d -p branch_11_e -m 11_M) &&
613+
git reset --hard $MERGE &&
614+
git checkout --orphan branch_11_a &&
615+
test_commit 11_A &&
616+
test_commit 11_A1 &&
617+
test_commit 11_A2 &&
618+
619+
check_graph branch_11_a branch_11_b <<-\EOF
620+
* 11_A2
621+
* 11_A1
622+
* 11_A
623+
*-. 11_M
624+
/|\ \
625+
| | | * 11_E
626+
| | * 11_D
627+
| * 11_C
628+
* 11_B
629+
EOF
630+
'
631+
632+
test_expect_success 'log --graph disconnected three roots cascading' '
633+
git checkout --orphan branch_12_d &&
634+
test_commit 12_D &&
635+
test_commit 12_D1 &&
636+
git checkout --orphan branch_12_c &&
637+
test_commit 12_C &&
638+
git checkout --orphan branch_12_b &&
639+
test_commit 12_B &&
640+
git checkout --orphan branch_12_a &&
641+
test_commit 12_A &&
642+
643+
check_graph branch_12_a branch_12_b branch_12_c branch_12_d <<-\EOF
644+
* 12_A
645+
* 12_B
646+
* 12_C
647+
* 12_D1
648+
_ /
649+
/
650+
/
651+
* 12_D
652+
EOF
653+
'
654+
517655
test_done

0 commit comments

Comments
 (0)