function renderSVG(commits) {
const svg = d3.create("svg");
svg.attr("height", 500);
svg.attr("width", 700);
const circleRadius = 15;
const margin = 30;
const columnWidth = 200;
const rowHeight = 50;
const lines = svg
.selectAll("line")
.data(commits)
.enter().append("g")
.selectAll("line")
.data(d => d.parentPositions.map(parent => ({ commit: d, parent })))
.enter().append("line")
.attr("x1", d => d.commit.column * columnWidth + margin)
.attr("y1", d => d.commit.height * rowHeight + margin)
.attr("x2", d => d.parent.column * columnWidth + margin)
.attr("y2", d => d.parent.height * rowHeight + margin)
.attr("stroke", "gray");
const circles = svg
.selectAll("circle")
.data(commits)
.enter()
.append("circle")
.attr("cx", (d) => d.column * columnWidth + margin)
.attr("cy", (d) => d.height * rowHeight + margin)
.attr("r", circleRadius)
.attr("fill", "white")
.attr("stroke", "black")
.attr("stroke-width", "2px");
svg
.selectAll("text.author")
.data(commits)
.enter()
.append("text")
.attr("class", "author")
.attr("x", (d) => d.column * columnWidth + margin - circleRadius / 2 - 1)
.attr("y", (d) => d.height * rowHeight + margin)
.attr("dy", "0.35em")
.text((d) => d.author.split(" ").map((x) => x[0]).join(""))
.attr("font-family", "Inconsolata");
svg
.selectAll("text.message")
.data(commits)
.enter()
.append("text")
.attr("class", "message")
.attr("x", (d) => d.column * columnWidth + margin + circleRadius + 5)
.attr("y", (d) => d.height * rowHeight + margin)
.attr("dy", "0.35em")
.text((d) => d.message);
return svg.node();
}