From: James Coglan <jcoglan@xxxxxxxxx> When a merge commit is printed and its final parent is the same commit that occupies the column to the right of the merge, this results in a kink in the displayed edges: * | |\ \ | |/ | * Graphs containing these shapes can be hard to read, as the expansion to the right followed immediately by collapsing back to the left creates a lot of zig-zagging edges, especially when many columns are present. We can improve this by eliminating the zig-zag and having the merge's final parent edge fuse immediately with its neighbor: * | |\| | * This reduces the horizontal width for the current commit by 2, and requires one less row, making the graph display more compact. Taken in combination with other graph-smoothing enhancements, it greatly compresses the space needed to display certain histories: * |\ | * * | |\ |\ | | * | * | | | | |\ | | \ | | * | *-. \ | * | | |\ \ \ => |/|\| |/ / / / | | * | | | / | * | | | |/ | |/ | | * * / | * | |/ | |/ * * | |/ * One of the test cases here cannot be correctly rendered in Git v2.23.0; it produces this output following commit E: | | *-. \ 5_E | | |\ \ \ | |/ / / / | | | / _ | |_|/ |/| | The new implementation makes sure that the rightmost edge in this history is not left dangling as above. Signed-off-by: James Coglan <jcoglan@xxxxxxxxx> --- graph.c | 34 ++++++--- t/t4215-log-skewed-merges.sh | 80 +++++++++++++++++++++- t/t6016-rev-list-graph-simplify-history.sh | 30 ++++---- 3 files changed, 116 insertions(+), 28 deletions(-) diff --git a/graph.c b/graph.c index 6391e393ec..7dd2fab625 100644 --- a/graph.c +++ b/graph.c @@ -538,8 +538,24 @@ static void graph_insert_into_new_columns(struct git_graph *graph, shift = (dist > 1) ? 2 * dist - 3 : 1; graph->merge_layout = (dist > 0) ? 0 : 1; + graph->edges_added = graph->num_parents + graph->merge_layout - 2; + mapping_idx = graph->width + (graph->merge_layout - 1) * shift; graph->width += 2 * graph->merge_layout; + + } else if (graph->edges_added > 0 && i == graph->mapping[graph->width - 2]) { + /* + * If some columns have been added by a merge, but this commit + * was found in the last existing column, then adjust the + * numbers so that the two edges immediately join, i.e.: + * + * * | * | + * |\ \ => |\| + * | |/ | * + * | * + */ + mapping_idx = graph->width - 2; + graph->edges_added = -1; } else { mapping_idx = graph->width; graph->width += 2; @@ -585,6 +601,8 @@ static void graph_update_columns(struct git_graph *graph) graph->mapping[i] = -1; graph->width = 0; + graph->prev_edges_added = graph->edges_added; + graph->edges_added = 0; /* * Populate graph->new_columns and graph->mapping @@ -712,9 +730,6 @@ void graph_update(struct git_graph *graph, struct commit *commit) */ graph_update_columns(graph); - graph->prev_edges_added = graph->edges_added; - graph->edges_added = graph->num_parents + graph->merge_layout - 2; - graph->expansion_row = 0; /* @@ -1039,7 +1054,7 @@ const char merge_chars[] = {'/', '|', '\\'}; static void graph_output_post_merge_line(struct git_graph *graph, struct strbuf *sb) { int seen_this = 0; - int i; + int i, j; struct commit_list *first_parent = first_interesting_parent(graph); int seen_parent = 0; @@ -1071,16 +1086,19 @@ static void graph_output_post_merge_line(struct git_graph *graph, struct strbuf char c; seen_this = 1; - for (; parents; parents = next_interesting_parent(graph, parents)) { + for (j = 0; j < graph->num_parents; j++) { par_column = graph_find_new_column_by_commit(graph, parents->item); assert(par_column >= 0); c = merge_chars[idx]; strbuf_write_column(sb, &graph->new_columns[par_column], c); - if (idx == 2) - strbuf_addch(sb, ' '); - else + if (idx == 2) { + if (graph->edges_added > 0 || j < graph->num_parents - 1) + strbuf_addch(sb, ' '); + } else { idx++; + } + parents = next_interesting_parent(graph, parents); } if (graph->edges_added == 0) strbuf_addch(sb, ' '); diff --git a/t/t4215-log-skewed-merges.sh b/t/t4215-log-skewed-merges.sh index b739268e5e..1481e6fd80 100755 --- a/t/t4215-log-skewed-merges.sh +++ b/t/t4215-log-skewed-merges.sh @@ -137,9 +137,8 @@ cat > expect <<\EOF | | * 3_G | * | 3_F |/| | -| * | 3_E -| |\ \ -| | |/ +| * | 3_E +| |\| | | * 3_D | * | 3_C | |/ @@ -190,4 +189,79 @@ test_expect_success 'log --graph with right-skewed merge following a left-skewed test_cmp expect actual ' +test_expect_success 'setup octopus merge with column joining its penultimate parent' ' + git checkout --orphan 5_p && + test_commit 5_A && + git branch 5_q && + git branch 5_r && + test_commit 5_B && + git checkout 5_q && test_commit 5_C && + git checkout 5_r && test_commit 5_D && + git checkout 5_p && + git merge --no-ff 5_q 5_r -m 5_E && + git checkout 5_q && test_commit 5_F && + git checkout -b 5_s 5_p^ && + git merge --no-ff 5_p 5_q -m 5_G && + git checkout 5_r && + git merge --no-ff 5_s -m 5_H +' + +cat > expect <<\EOF +* 5_H +|\ +| *-. 5_G +| |\ \ +| | | * 5_F +| | * | 5_E +| |/|\ \ +| |_|/ / +|/| | / +| | |/ +* | | 5_D +| | * 5_C +| |/ +|/| +| * 5_B +|/ +* 5_A +EOF + +test_expect_success 'log --graph with octopus merge with column joining its penultimate parent' ' + git log --graph --pretty=tformat:%s | sed "s/ *$//" > actual && + test_cmp expect actual +' + +test_expect_success 'setup merge fusing with its left and right neighbors' ' + git checkout --orphan 6_p && + test_commit 6_A && + test_commit 6_B && + git checkout -b 6_q @^ && test_commit 6_C && + git checkout -b 6_r @^ && test_commit 6_D && + git checkout 6_p && git merge --no-ff 6_q 6_r -m 6_E && + git checkout 6_r && test_commit 6_F && + git checkout 6_p && git merge --no-ff 6_r -m 6_G && + git checkout @^^ && git merge --no-ff 6_p -m 6_H +' + +cat > expect <<\EOF +* 6_H +|\ +| * 6_G +| |\ +| | * 6_F +| * | 6_E +|/|\| +| | * 6_D +| * | 6_C +| |/ +* / 6_B +|/ +* 6_A +EOF + +test_expect_success 'log --graph with merge fusing with its left and right neighbors' ' + git log --graph --pretty=tformat:%s | sed "s/ *$//" > actual && + test_cmp expect actual +' + test_done diff --git a/t/t6016-rev-list-graph-simplify-history.sh b/t/t6016-rev-list-graph-simplify-history.sh index ca1682f29b..f5e6e92f5b 100755 --- a/t/t6016-rev-list-graph-simplify-history.sh +++ b/t/t6016-rev-list-graph-simplify-history.sh @@ -67,11 +67,10 @@ test_expect_success '--graph --all' ' echo "| * $C4" >> expected && echo "| * $C3" >> expected && echo "* | $A5" >> expected && - echo "| | " >> expected && - echo "| \\ " >> expected && - echo "*-. \\ $A4" >> expected && - echo "|\\ \\ \\ " >> expected && - echo "| | |/ " >> expected && + echo "| | " >> expected && + echo "| \\ " >> expected && + echo "*-. | $A4" >> expected && + echo "|\\ \\| " >> expected && echo "| | * $C2" >> expected && echo "| | * $C1" >> expected && echo "| * | $B2" >> expected && @@ -97,11 +96,10 @@ test_expect_success '--graph --simplify-by-decoration' ' echo "| * $C4" >> expected && echo "| * $C3" >> expected && echo "* | $A5" >> expected && - echo "| | " >> expected && - echo "| \\ " >> expected && - echo "*-. \\ $A4" >> expected && - echo "|\\ \\ \\ " >> expected && - echo "| | |/ " >> expected && + echo "| | " >> expected && + echo "| \\ " >> expected && + echo "*-. | $A4" >> expected && + echo "|\\ \\| " >> expected && echo "| | * $C2" >> expected && echo "| | * $C1" >> expected && echo "| * | $B2" >> expected && @@ -131,9 +129,8 @@ test_expect_success '--graph --simplify-by-decoration prune branch B' ' echo "| * $C4" >> expected && echo "| * $C3" >> expected && echo "* | $A5" >> expected && - echo "* | $A4" >> expected && - echo "|\\ \\ " >> expected && - echo "| |/ " >> expected && + echo "* | $A4" >> expected && + echo "|\\| " >> expected && echo "| * $C2" >> expected && echo "| * $C1" >> expected && echo "* | $A3" >> expected && @@ -151,10 +148,9 @@ test_expect_success '--graph --full-history -- bar.txt' ' echo "|\\ " >> expected && echo "| * $C4" >> expected && echo "* | $A5" >> expected && - echo "* | $A4" >> expected && - echo "|\\ \\ " >> expected && - echo "| |/ " >> expected && - echo "* / $A3" >> expected && + echo "* | $A4" >> expected && + echo "|\\| " >> expected && + echo "* | $A3" >> expected && echo "|/ " >> expected && echo "* $A2" >> expected && git rev-list --graph --full-history --all -- bar.txt > actual && -- gitgitgadget