Skip to content

Commit 04ba516

Browse files
committed
graph: flatten edges that fuse with their right neighbor
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 <[email protected]>
1 parent 9b24893 commit 04ba516

File tree

3 files changed

+86
-34
lines changed

3 files changed

+86
-34
lines changed

graph.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -557,8 +557,24 @@ static void graph_insert_into_new_columns(struct git_graph *graph,
557557
shift = (dist > 1) ? 2 * dist - 3 : 1;
558558

559559
graph->merge_layout = (dist > 0) ? 0 : 1;
560+
graph->edges_added = graph->num_parents + graph->merge_layout - 2;
561+
560562
mapping_idx = graph->width + (graph->merge_layout - 1) * shift;
561563
graph->width += 2 * graph->merge_layout;
564+
565+
} else if (graph->edges_added > 0 && i == graph->mapping[graph->width - 2]) {
566+
/*
567+
* If some columns have been added by a merge, but this commit
568+
* was found in the last existing column, then adjust the
569+
* numbers so that the two edges immediately join, i.e.:
570+
*
571+
* * | * |
572+
* |\ \ => |\|
573+
* | |/ | *
574+
* | *
575+
*/
576+
mapping_idx = graph->width - 2;
577+
graph->edges_added = -1;
562578
} else {
563579
mapping_idx = graph->width;
564580
graph->width += 2;
@@ -604,6 +620,8 @@ static void graph_update_columns(struct git_graph *graph)
604620
graph->mapping[i] = -1;
605621

606622
graph->width = 0;
623+
graph->prev_edges_added = graph->edges_added;
624+
graph->edges_added = 0;
607625

608626
/*
609627
* Populate graph->new_columns and graph->mapping
@@ -731,9 +749,6 @@ void graph_update(struct git_graph *graph, struct commit *commit)
731749
*/
732750
graph_update_columns(graph);
733751

734-
graph->prev_edges_added = graph->edges_added;
735-
graph->edges_added = graph->num_parents + graph->merge_layout - 2;
736-
737752
graph->expansion_row = 0;
738753

739754
/*
@@ -1041,7 +1056,7 @@ const char merge_chars[] = {'/', '|', '\\'};
10411056
static void graph_output_post_merge_line(struct git_graph *graph, struct graph_line *line)
10421057
{
10431058
int seen_this = 0;
1044-
int i;
1059+
int i, j;
10451060

10461061
struct commit_list *first_parent = first_interesting_parent(graph);
10471062
int seen_parent = 0;
@@ -1073,16 +1088,19 @@ static void graph_output_post_merge_line(struct git_graph *graph, struct graph_l
10731088
char c;
10741089
seen_this = 1;
10751090

1076-
for (; parents; parents = next_interesting_parent(graph, parents)) {
1091+
for (j = 0; j < graph->num_parents; j++) {
10771092
par_column = graph_find_new_column_by_commit(graph, parents->item);
10781093
assert(par_column >= 0);
10791094

10801095
c = merge_chars[idx];
10811096
graph_line_write_column(line, &graph->new_columns[par_column], c);
1082-
if (idx == 2)
1083-
graph_line_addch(line, ' ');
1084-
else
1097+
if (idx == 2) {
1098+
if (graph->edges_added > 0 || j < graph->num_parents - 1)
1099+
graph_line_addch(line, ' ');
1100+
} else {
10851101
idx++;
1102+
}
1103+
parents = next_interesting_parent(graph, parents);
10861104
}
10871105
if (graph->edges_added == 0)
10881106
graph_line_addch(line, ' ');

t/t4215-log-skewed-merges.sh

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@ test_expect_success 'log --graph with merge fusing with its left and right neigh
1111
| * G
1212
| |\
1313
| | * F
14-
| * | E
15-
|/|\ \
16-
| | |/
14+
| * | E
15+
|/|\|
1716
| | * D
1817
| * | C
1918
| |/
@@ -43,9 +42,9 @@ test_expect_success 'log --graph with left-skewed merge' '
4342
| | | | * 0_G
4443
| |_|_|/|
4544
|/| | | |
46-
| | | * | 0_F
47-
| |_|/|\ \
48-
|/| | | |/
45+
| | | * | 0_F
46+
| |_|/|\|
47+
|/| | | |
4948
| | | | * 0_E
5049
| |_|_|/
5150
|/| | |
@@ -153,9 +152,8 @@ test_expect_success 'log --graph with nested right-skewed merge following left-s
153152
| | * 3_G
154153
| * | 3_F
155154
|/| |
156-
| * | 3_E
157-
| |\ \
158-
| | |/
155+
| * | 3_E
156+
| |\|
159157
| | * 3_D
160158
| * | 3_C
161159
| |/
@@ -216,4 +214,44 @@ test_expect_success 'log --graph with right-skewed merge following a left-skewed
216214
test_cmp expect actual
217215
'
218216

217+
test_expect_success 'log --graph with octopus merge with column joining its penultimate parent' '
218+
cat >expect <<-\EOF &&
219+
* 5_H
220+
|\
221+
| *-. 5_G
222+
| |\ \
223+
| | | * 5_F
224+
| | * | 5_E
225+
| |/|\ \
226+
| |_|/ /
227+
|/| | /
228+
| | |/
229+
* | | 5_D
230+
| | * 5_C
231+
| |/
232+
|/|
233+
| * 5_B
234+
|/
235+
* 5_A
236+
EOF
237+
238+
git checkout --orphan 5_p &&
239+
test_commit 5_A &&
240+
git branch 5_q &&
241+
git branch 5_r &&
242+
test_commit 5_B &&
243+
git checkout 5_q && test_commit 5_C &&
244+
git checkout 5_r && test_commit 5_D &&
245+
git checkout 5_p &&
246+
git merge --no-ff 5_q 5_r -m 5_E &&
247+
git checkout 5_q && test_commit 5_F &&
248+
git checkout -b 5_s 5_p^ &&
249+
git merge --no-ff 5_p 5_q -m 5_G &&
250+
git checkout 5_r &&
251+
git merge --no-ff 5_s -m 5_H &&
252+
253+
git log --graph --pretty=tformat:%s | sed "s/ *$//" >actual &&
254+
test_cmp expect actual
255+
'
256+
219257
test_done

t/t6016-rev-list-graph-simplify-history.sh

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,10 @@ test_expect_success '--graph --all' '
6767
echo "| * $C4" >> expected &&
6868
echo "| * $C3" >> expected &&
6969
echo "* | $A5" >> expected &&
70-
echo "| | " >> expected &&
71-
echo "| \\ " >> expected &&
72-
echo "*-. \\ $A4" >> expected &&
73-
echo "|\\ \\ \\ " >> expected &&
74-
echo "| | |/ " >> expected &&
70+
echo "| | " >> expected &&
71+
echo "| \\ " >> expected &&
72+
echo "*-. | $A4" >> expected &&
73+
echo "|\\ \\| " >> expected &&
7574
echo "| | * $C2" >> expected &&
7675
echo "| | * $C1" >> expected &&
7776
echo "| * | $B2" >> expected &&
@@ -97,11 +96,10 @@ test_expect_success '--graph --simplify-by-decoration' '
9796
echo "| * $C4" >> expected &&
9897
echo "| * $C3" >> expected &&
9998
echo "* | $A5" >> expected &&
100-
echo "| | " >> expected &&
101-
echo "| \\ " >> expected &&
102-
echo "*-. \\ $A4" >> expected &&
103-
echo "|\\ \\ \\ " >> expected &&
104-
echo "| | |/ " >> expected &&
99+
echo "| | " >> expected &&
100+
echo "| \\ " >> expected &&
101+
echo "*-. | $A4" >> expected &&
102+
echo "|\\ \\| " >> expected &&
105103
echo "| | * $C2" >> expected &&
106104
echo "| | * $C1" >> expected &&
107105
echo "| * | $B2" >> expected &&
@@ -131,9 +129,8 @@ test_expect_success '--graph --simplify-by-decoration prune branch B' '
131129
echo "| * $C4" >> expected &&
132130
echo "| * $C3" >> expected &&
133131
echo "* | $A5" >> expected &&
134-
echo "* | $A4" >> expected &&
135-
echo "|\\ \\ " >> expected &&
136-
echo "| |/ " >> expected &&
132+
echo "* | $A4" >> expected &&
133+
echo "|\\| " >> expected &&
137134
echo "| * $C2" >> expected &&
138135
echo "| * $C1" >> expected &&
139136
echo "* | $A3" >> expected &&
@@ -151,10 +148,9 @@ test_expect_success '--graph --full-history -- bar.txt' '
151148
echo "|\\ " >> expected &&
152149
echo "| * $C4" >> expected &&
153150
echo "* | $A5" >> expected &&
154-
echo "* | $A4" >> expected &&
155-
echo "|\\ \\ " >> expected &&
156-
echo "| |/ " >> expected &&
157-
echo "* / $A3" >> expected &&
151+
echo "* | $A4" >> expected &&
152+
echo "|\\| " >> expected &&
153+
echo "* | $A3" >> expected &&
158154
echo "|/ " >> expected &&
159155
echo "* $A2" >> expected &&
160156
git rev-list --graph --full-history --all -- bar.txt > actual &&

0 commit comments

Comments
 (0)