Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 200 additions & 0 deletions git_analytics/analyze_git_activity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
#!/usr/bin/env python3
"""Build a professional dashboard for pull-request and merge activity."""

from __future__ import annotations

import csv
import json
import re
import subprocess
from collections import Counter
from datetime import datetime
from pathlib import Path

ROOT = Path(__file__).resolve().parent
OUT_CSV = ROOT / "merge_pr_activity.csv"
OUT_HTML = ROOT / "merge_pr_activity.html"
OUT_MD = ROOT / "merge_pr_summary.md"

LOG_FORMAT = "%H|%ad|%s"
DATE_FORMAT = "%Y-%m-%d"
PR_RE = re.compile(r"Merge pull request #(\d+)", re.IGNORECASE)
FROM_RE = re.compile(r"\sfrom\s([^/\s]+)/?([^\s]*)", re.IGNORECASE)


def run_git_log() -> list[str]:
cmd = ["git", "log", "--merges", "--date=short", f"--pretty=format:{LOG_FORMAT}"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Limit merge analytics to first-parent history

Using git log --merges without --first-parent walks all parents, so merges that happened on side/topic branches are included in the dataset and can distort totals and trends for the main integration branch. In repos where teams regularly merge upstream into feature branches, this will inflate merge counts and make the monthly/weekday metrics report activity that was never merged directly into the target branch.

Useful? React with 👍 / 👎.

result = subprocess.run(cmd, check=True, text=True, capture_output=True)
return [line.strip() for line in result.stdout.splitlines() if line.strip()]


def parse_lines(lines: list[str]) -> list[dict[str, str | int | None]]:
rows = []
for line in lines:
commit, date, subject = line.split("|", 2)
pr_match = PR_RE.search(subject)
from_match = FROM_RE.search(subject)
author = from_match.group(1) if from_match else "unknown"
source_branch = from_match.group(2) if from_match else "unknown"
pr_number = int(pr_match.group(1)) if pr_match else None
dt = datetime.strptime(date, DATE_FORMAT)
rows.append(
{
"commit": commit,
"date": date,
"month": dt.strftime("%Y-%m"),
"weekday": dt.strftime("%A"),
"subject": subject,
"pr_number": pr_number,
"is_pr_merge": int(pr_number is not None),
"author": author,
"source_branch": source_branch,
}
)
return rows


def write_csv(rows: list[dict[str, str | int | None]]) -> None:
fields = ["commit", "date", "month", "weekday", "subject", "pr_number", "is_pr_merge", "author", "source_branch"]
with OUT_CSV.open("w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=fields)
writer.writeheader()
writer.writerows(rows)


def write_html(rows: list[dict[str, str | int | None]]) -> None:
merges_by_month = Counter(str(r["month"]) for r in rows)
pr_by_month = Counter(str(r["month"]) for r in rows if r["is_pr_merge"])
weekday_order = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
merges_by_weekday = Counter(str(r["weekday"]) for r in rows)
top_authors = Counter(str(r["author"]) for r in rows if str(r["author"]) != "unknown")

months = sorted(set(merges_by_month) | set(pr_by_month))
total_merges = len(rows)
total_pr_merges = sum(int(r["is_pr_merge"]) for r in rows)
pr_numbers = sorted(int(r["pr_number"]) for r in rows if r["pr_number"] is not None)
first_pr, last_pr = (pr_numbers[0], pr_numbers[-1]) if pr_numbers else (None, None)

table_rows = rows[:100]

html = f"""<!doctype html>
<html>
<head>
<meta charset='utf-8'>
<title>Professional Pull Request Dashboard</title>
<script src='https://cdn.plot.ly/plotly-2.35.2.min.js'></script>
<style>
body{{font-family:Inter,Segoe UI,Arial,sans-serif;background:#0b1020;color:#e9eefc;margin:0;padding:24px;}}
h1{{margin:0 0 12px 0;}}
.sub{{color:#a8b2d1;margin-bottom:18px}}
.kpi{{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:16px 0 24px;}}
.card{{background:#151b31;border:1px solid #2a3358;border-radius:12px;padding:14px;}}
.k{{font-size:12px;color:#a8b2d1}} .v{{font-size:28px;font-weight:700;margin-top:6px}}
.charts{{display:grid;grid-template-columns:2fr 1fr;gap:12px;}}
.charts2{{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:12px;}}
#prTable{{width:100%;border-collapse:collapse;font-size:12px}}
#prTable th,#prTable td{{border-bottom:1px solid #2a3358;padding:8px;text-align:left}}
#prTable th{{color:#a8b2d1}}
input{{background:#0f1428;color:#e9eefc;border:1px solid #2a3358;border-radius:8px;padding:8px 10px;min-width:260px;margin:8px 0 12px;}}
</style>
</head>
<body>
<h1>Professional Pull Request Dashboard</h1>
<div class='sub'>Generated from merge history (`git log --merges`) • Interactive analysis for PR trends.</div>

<div class='kpi'>
<div class='card'><div class='k'>Total Merge Commits</div><div class='v'>{total_merges}</div></div>
<div class='card'><div class='k'>PR Merge Commits</div><div class='v'>{total_pr_merges}</div></div>
<div class='card'><div class='k'>First PR Number</div><div class='v'>{first_pr if first_pr is not None else 'N/A'}</div></div>
<div class='card'><div class='k'>Latest PR Number</div><div class='v'>{last_pr if last_pr is not None else 'N/A'}</div></div>
</div>

<div class='charts'>
<div class='card'><div id='monthChart'></div></div>
<div class='card'><div id='typeChart'></div></div>
</div>
<div class='charts2'>
<div class='card'><div id='weekdayChart'></div></div>
<div class='card'><div id='authorChart'></div></div>
</div>

<div class='card' style='margin-top:12px'>
<h3 style='margin-top:0'>Recent Merge/PR Records (Top 100)</h3>
<input id='search' placeholder='Filter by PR number, commit, branch, author, or subject...' onkeyup='filterTable()' />
<table id='prTable'>
<thead><tr><th>Date</th><th>PR</th><th>Author</th><th>Branch</th><th>Commit</th><th>Subject</th></tr></thead>
<tbody></tbody>
</table>
</div>

<script>
const months = {json.dumps(months)};
const monthMerge = {json.dumps([merges_by_month[m] for m in months])};
const monthPR = {json.dumps([pr_by_month.get(m, 0) for m in months])};
const weekday = {json.dumps(weekday_order)};
const weekdayVals = {json.dumps([merges_by_weekday.get(d, 0) for d in weekday_order])};
const authorNames = {json.dumps([k for k, _ in top_authors.most_common(10)])};
const authorVals = {json.dumps([v for _, v in top_authors.most_common(10)])};
const tableData = {json.dumps(table_rows)};

const commonLayout = {{paper_bgcolor:'#151b31', plot_bgcolor:'#151b31', font:{{color:'#e9eefc'}}}};
Plotly.newPlot('monthChart', [
{{x: months, y: monthMerge, name:'All merges', type:'scatter', mode:'lines+markers'}},
{{x: months, y: monthPR, name:'PR merges', type:'scatter', mode:'lines+markers'}}
], {{...commonLayout, title:'Monthly Pull/Merge Trend', xaxis:{{title:'Month'}}, yaxis:{{title:'Count'}}}});

Plotly.newPlot('typeChart', [{{type:'pie', labels:['PR merges','Other merges'], values:[{total_pr_merges},{total_merges-total_pr_merges}], hole:0.48}}], {{...commonLayout, title:'Merge Type Split'}});
Plotly.newPlot('weekdayChart', [{{x:weekday, y:weekdayVals, type:'bar', marker:{{color:'#53a7ff'}}}}], {{...commonLayout, title:'Merge Activity by Weekday', yaxis:{{title:'Count'}}}});
Plotly.newPlot('authorChart', [{{x:authorVals, y:authorNames, type:'bar', orientation:'h', marker:{{color:'#7bd88f'}}}}], {{...commonLayout, title:'Top PR Sources (from merge text)', xaxis:{{title:'Merge count'}}}});

function renderTable(rows) {{
const tbody = document.querySelector('#prTable tbody');
tbody.innerHTML = rows.map(r => `<tr><td>${{r.date}}</td><td>${{r.pr_number ?? ''}}</td><td>${{r.author}}</td><td>${{r.source_branch}}</td><td><code>${{r.commit.slice(0,8)}}</code></td><td>${{r.subject}}</td></tr>`).join('');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Escape merge fields before writing table HTML

The dashboard renders commit-derived strings (subject, author, source_branch) directly into innerHTML, so a merge commit message containing HTML/JS (for example from a PR title in a public repo) will execute when someone opens the generated report. Because these fields come from git log and are attacker-controllable in collaborative repositories, this introduces a stored XSS vector in the artifact.

Useful? React with 👍 / 👎.

}}
Comment on lines +138 to +153

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Prevent script/HTML injection from git metadata before rendering

Git-derived fields (notably subject) are embedded in inline JS and then rendered with innerHTML. A crafted merge subject can break out of <script> or execute in the table context.

🔐 Suggested hardening patch
@@
-    table_rows = rows[:100]
+    table_rows = rows[:100]
+    safe_table_json = json.dumps(table_rows).replace("</", "<\\/")
@@
-const tableData = {json.dumps(table_rows)};
+const tableData = {safe_table_json};
@@
 function renderTable(rows) {{
   const tbody = document.querySelector('`#prTable` tbody');
-  tbody.innerHTML = rows.map(r => `<tr><td>${{r.date}}</td><td>${{r.pr_number ?? ''}}</td><td>${{r.author}}</td><td>${{r.source_branch}}</td><td><code>${{r.commit.slice(0,8)}}</code></td><td>${{r.subject}}</td></tr>`).join('');
+  tbody.textContent = '';
+  for (const r of rows) {{
+    const tr = document.createElement('tr');
+    const values = [r.date, r.pr_number ?? '', r.author, r.source_branch, r.commit.slice(0, 8), r.subject];
+    values.forEach((value, idx) => {{
+      const td = document.createElement('td');
+      if (idx === 4) {{
+        const code = document.createElement('code');
+        code.textContent = String(value);
+        td.appendChild(code);
+      }} else {{
+        td.textContent = String(value);
+      }}
+      tr.appendChild(td);
+    }});
+    tbody.appendChild(tr);
+  }}
 }}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@git_analytics/analyze_git_activity.py` around lines 138 - 153, The
renderTable function currently builds HTML via tbody.innerHTML using template
interpolation of git-derived fields (e.g., r.subject, r.author, r.source_branch,
r.commit, r.pr_number) which allows script/HTML injection; fix it by avoiding
direct innerHTML construction: either HTML-escape/encode those fields before
interpolation or (preferably) create DOM elements with document.createElement
and set textContent for each cell so values are treated as text, then append
rows to the tbody; update renderTable to use this safe rendering approach and
ensure the same escaping is applied wherever tableData or subject is used in
inline JS.


function filterTable() {{
const q = document.getElementById('search').value.toLowerCase();
const rows = tableData.filter(r => JSON.stringify(r).toLowerCase().includes(q));
renderTable(rows);
}}

renderTable(tableData);
</script>
</body></html>"""

OUT_HTML.write_text(html, encoding="utf-8")


def write_markdown(rows: list[dict[str, str | int | None]]) -> None:
merges_by_month = Counter(str(r["month"]) for r in rows)
top_month = max(merges_by_month.items(), key=lambda x: x[1]) if merges_by_month else ("N/A", 0)
top_author = Counter(str(r["author"]) for r in rows if str(r["author"]) != "unknown").most_common(1)
total_merges = len(rows)
total_pr = sum(int(r["is_pr_merge"]) for r in rows)
pr_numbers = [int(r["pr_number"]) for r in rows if r["pr_number"] is not None]

lines = [
"# Professional Git Pull/Merge Dashboard Summary",
"",
f"- Total merge commits: **{total_merges}**",
f"- PR merge commits: **{total_pr}**",
f"- Non-PR merges: **{total_merges - total_pr}**",
f"- PR range: **#{min(pr_numbers)} to #{max(pr_numbers)}**" if pr_numbers else "- PR range: N/A",
f"- Peak month: **{top_month[0]}** ({top_month[1]} merges)",
f"- Top source author in merge text: **{top_author[0][0]}** ({top_author[0][1]} merges)" if top_author else "- Top source author: N/A",
"",
"Open `git_analytics/merge_pr_activity.html` for the full professional dashboard.",
]
OUT_MD.write_text("\n".join(lines), encoding="utf-8")


def main() -> None:
rows = parse_lines(run_git_log())
write_csv(rows)
write_html(rows)
write_markdown(rows)
print(f"Processed {len(rows)} merge commits into professional dashboard artifacts.")


if __name__ == "__main__":
main()
68 changes: 68 additions & 0 deletions git_analytics/merge_pr_activity.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
commit,date,month,weekday,subject,pr_number,is_pr_merge,author,source_branch
b8f962e242f4fe7e4f754b0189410104d24eb9ff,2026-05-25,2026-05,Monday,Merge pull request #76 from Ritik574-coder/dbt_branch,76,1,Ritik574-coder,dbt_branch
d6bfa79a5c738de07c68f093eb077562fb08712e,2026-05-25,2026-05,Monday,Merge pull request #75 from Ritik574-coder/dbt_branch,75,1,Ritik574-coder,dbt_branch
f55e9dcfd026227588a6fd188d47a058b97b18ad,2026-05-24,2026-05,Sunday,Merge pull request #74 from Ritik574-coder/dbt_branch,74,1,Ritik574-coder,dbt_branch
11dfff130115df45de1d1e2089a54dcb6c44f863,2026-05-23,2026-05,Saturday,Merge pull request #73 from Ritik574-coder/dbt_branch,73,1,Ritik574-coder,dbt_branch
044418bae08c3e9f1ab4387af3abd4568473cc1a,2026-05-23,2026-05,Saturday,Merge pull request #72 from Ritik574-coder/dbt_branch,72,1,Ritik574-coder,dbt_branch
a5b8dd149488771fbc4b2e73c1d484a69e02d270,2026-05-22,2026-05,Friday,Merge pull request #71 from Ritik574-coder/dbt_branch,71,1,Ritik574-coder,dbt_branch
036421b56e0075a924316a52c8bb307cec621fc4,2026-05-21,2026-05,Thursday,Merge pull request #70 from Ritik574-coder/dbt_branch,70,1,Ritik574-coder,dbt_branch
34e749b0ce566e8e9c808dc62329eb0e7348e940,2026-05-21,2026-05,Thursday,Merge pull request #69 from Ritik574-coder/dbt_branch,69,1,Ritik574-coder,dbt_branch
ea8f002b57aec7d280cbe68803c801b8c45c0d92,2026-05-21,2026-05,Thursday,Merge pull request #68 from Ritik574-coder/dbt_branch,68,1,Ritik574-coder,dbt_branch
ce5f4857bd890253d7304a1e6a4f0246cc1a8087,2026-05-20,2026-05,Wednesday,Merge pull request #67 from Ritik574-coder/dbt_branch,67,1,Ritik574-coder,dbt_branch
7ccf2a710300526f65aa83df9d956128c2fbad52,2026-05-20,2026-05,Wednesday,Merge pull request #66 from Ritik574-coder/dbt_branch,66,1,Ritik574-coder,dbt_branch
3f98986ffeb5f94eceeea2888ba7e0a1dabeb7e0,2026-05-20,2026-05,Wednesday,Merge pull request #65 from Ritik574-coder/dbt_branch,65,1,Ritik574-coder,dbt_branch
b296a101e99b7e594fb149c38d0ec14b7e7d2119,2026-05-19,2026-05,Tuesday,Merge pull request #64 from Ritik574-coder/dbt_branch,64,1,Ritik574-coder,dbt_branch
96f1e480b24936c93d9d67ad04d5de0c18465166,2026-05-18,2026-05,Monday,Merge pull request #63 from Ritik574-coder/dbt_branch,63,1,Ritik574-coder,dbt_branch
116ec9451d86d023b2883af7e26b5f5fccbaffd9,2026-05-18,2026-05,Monday,Merge pull request #62 from Ritik574-coder/dbt_branch,62,1,Ritik574-coder,dbt_branch
76e73c5b9eec4ab8f14e681b0aa130ee3ab8b2be,2026-05-17,2026-05,Sunday,Merge pull request #61 from Ritik574-coder/dbt_branch,61,1,Ritik574-coder,dbt_branch
afe17e6bc3dfc90c0c82872c4a772d66c33baeab,2026-05-17,2026-05,Sunday,Merge pull request #60 from Ritik574-coder/dbt_branch,60,1,Ritik574-coder,dbt_branch
ef07904295bda741bbfe7fa83b2584b3523e059a,2026-05-17,2026-05,Sunday,Merge pull request #59 from Ritik574-coder/dbt_branch,59,1,Ritik574-coder,dbt_branch
4287da02eae902c0f29bad1a9398c8871dc142c7,2026-05-16,2026-05,Saturday,Merge pull request #58 from Ritik574-coder/dbt_branch,58,1,Ritik574-coder,dbt_branch
674d9d37f5583e1873488d3b9e1ba38dc8765c10,2026-05-16,2026-05,Saturday,Merge pull request #57 from Ritik574-coder/dbt_branch,57,1,Ritik574-coder,dbt_branch
54975ff6f77b9bef4d05d9fc73124eca239f9c62,2026-05-16,2026-05,Saturday,Merge pull request #56 from Ritik574-coder/dbt_branch,56,1,Ritik574-coder,dbt_branch
e11915a343fb859a721592403805115f0314b7a0,2026-05-15,2026-05,Friday,Merge pull request #55 from Ritik574-coder/dbt_branch,55,1,Ritik574-coder,dbt_branch
711f5afb901528657fec260c33d7f37cfb594e19,2026-05-15,2026-05,Friday,Merge pull request #54 from Ritik574-coder/dbt_branch,54,1,Ritik574-coder,dbt_branch
3a50b0c083334cf91a19a232c34f7ce5dacf7d16,2026-05-15,2026-05,Friday,Merge pull request #53 from Ritik574-coder/dbt_branch,53,1,Ritik574-coder,dbt_branch
750595f11b41145e53470be4a68f52c43e0f6acf,2026-05-14,2026-05,Thursday,Merge pull request #52 from Ritik574-coder/dbt_branch,52,1,Ritik574-coder,dbt_branch
ff4ae559841c22c5696214d4f7dc13ee84ceab69,2026-05-14,2026-05,Thursday,Merge pull request #51 from Ritik574-coder/dbt_branch,51,1,Ritik574-coder,dbt_branch
d5ae3cc9a1563ddddbfa3c583542bb9719dd1833,2026-05-14,2026-05,Thursday,Merge pull request #48 from Ritik574-coder/dbt_branch,48,1,Ritik574-coder,dbt_branch
d130178e0a416009313743250a36c47ac988af1b,2026-05-13,2026-05,Wednesday,Merge pull request #47 from Ritik574-coder/dbt_branch,47,1,Ritik574-coder,dbt_branch
fe5952b488bb1164c2ae8250feb735c283242396,2026-05-13,2026-05,Wednesday,Merge pull request #46 from Ritik574-coder/dbt_branch,46,1,Ritik574-coder,dbt_branch
692b559fd7f411351442081867814a00594d7cd4,2026-05-13,2026-05,Wednesday,Merge pull request #45 from Ritik574-coder/dbt_branch,45,1,Ritik574-coder,dbt_branch
7ab4485da27ef58cdeba261cc548f77d562d0fa1,2026-05-12,2026-05,Tuesday,Merge pull request #44 from Ritik574-coder/dbt_branch,44,1,Ritik574-coder,dbt_branch
2211c9ed8904147f2fa3b302c1f19d959efa59c8,2026-05-12,2026-05,Tuesday,Merge pull request #43 from Ritik574-coder/dbt_branch,43,1,Ritik574-coder,dbt_branch
ac7363bf731af71cc376ef51f907be5432963a07,2026-05-11,2026-05,Monday,Merge pull request #42 from Ritik574-coder/dbt_branch,42,1,Ritik574-coder,dbt_branch
2d18b65257b7177b0b01c98585fd7378002ea7fd,2026-05-11,2026-05,Monday,Merge pull request #41 from Ritik574-coder/dbt_branch,41,1,Ritik574-coder,dbt_branch
f485e706e5c650c6dacfd38e310c3d1ddaeef58a,2026-05-11,2026-05,Monday,Merge pull request #40 from Ritik574-coder/dbt_branch,40,1,Ritik574-coder,dbt_branch
ea8bde836ad8790ff3e32c82ed4c6a41bab7114d,2026-05-11,2026-05,Monday,Merge pull request #39 from Ritik574-coder/dbt_branch,39,1,Ritik574-coder,dbt_branch
4442793431d72b6cbeef1eaa40f5c0ecab138bf9,2026-05-11,2026-05,Monday,Merge pull request #38 from Ritik574-coder/dbt_branch,38,1,Ritik574-coder,dbt_branch
812d76dd6c221eb8eb3ab63b39142378bbb7323a,2026-05-10,2026-05,Sunday,Merge pull request #37 from Ritik574-coder/dbt_branch,37,1,Ritik574-coder,dbt_branch
c600a0903e3380a55960075e7c01e186108a1aa4,2026-05-10,2026-05,Sunday,Merge pull request #36 from Ritik574-coder/dbt_branch,36,1,Ritik574-coder,dbt_branch
a7151576694df6e6bfa45efd8bdea44d05db3885,2026-05-10,2026-05,Sunday,Merge pull request #35 from Ritik574-coder/dbt_branch,35,1,Ritik574-coder,dbt_branch
282ddf9f1dbcc306b1228e87d24d4025c20a4846,2026-05-10,2026-05,Sunday,Merge pull request #34 from Ritik574-coder/dbt_branch,34,1,Ritik574-coder,dbt_branch
f07675e61d3356d40ec74542b65d10ee685d87ed,2026-05-09,2026-05,Saturday,Merge pull request #27 from Ritik574-coder/dbt_branch,27,1,Ritik574-coder,dbt_branch
893be9a3df972c9d8b421e03e1a8c0418ac76f41,2026-05-09,2026-05,Saturday,Merge pull request #26 from Ritik574-coder/dbt_branch,26,1,Ritik574-coder,dbt_branch
78f131d9a28f1726d261455a643545e2104d558f,2026-05-09,2026-05,Saturday,Merge pull request #25 from Ritik574-coder/dbt_branch,25,1,Ritik574-coder,dbt_branch
6a287e91655849d74a20019b5facde4c1cbbe62f,2026-05-09,2026-05,Saturday,Merge pull request #24 from Ritik574-coder/dbt_branch,24,1,Ritik574-coder,dbt_branch
e952a20385a1307f47a5bad463c27aaf8db08f43,2026-05-08,2026-05,Friday,Merge pull request #23 from Ritik574-coder/dbt_branch,23,1,Ritik574-coder,dbt_branch
0c8bd0be3ba72a88a986100b655dd85cafc7de89,2026-05-07,2026-05,Thursday,Merge pull request #22 from Ritik574-coder/dbt_branch,22,1,Ritik574-coder,dbt_branch
ac383a3c20f1a52a2ee0059c3a78d86f78fe08da,2026-05-07,2026-05,Thursday,Merge pull request #20 from Ritik574-coder/dbt_branch,20,1,Ritik574-coder,dbt_branch
ac50486918198ae7c8470d8a865c437adc895975,2026-05-06,2026-05,Wednesday,Merge pull request #19 from Ritik574-coder/dbt_branch,19,1,Ritik574-coder,dbt_branch
1d31a646da1c53f389a821341873207253d8638c,2026-05-06,2026-05,Wednesday,Merge pull request #18 from Ritik574-coder/dbt_branch,18,1,Ritik574-coder,dbt_branch
83cb669e02c47317eea99682b272ad7b2d2cedd9,2026-05-06,2026-05,Wednesday,Merge pull request #17 from Ritik574-coder/dbt_branch,17,1,Ritik574-coder,dbt_branch
940075ec99381b029283193829d753f821333764,2026-05-05,2026-05,Tuesday,Merge pull request #16 from Ritik574-coder/dbt_branch,16,1,Ritik574-coder,dbt_branch
afe2642426eb4ed29525b6e5ee5993fbd1c0144b,2026-05-05,2026-05,Tuesday,Merge pull request #15 from Ritik574-coder/main,15,1,Ritik574-coder,main
a04b75442a245d1a30d54c501fbb8d339d8be5c2,2026-05-05,2026-05,Tuesday,Merge pull request #14 from Ritik574-coder/dbt_branch,14,1,Ritik574-coder,dbt_branch
a1467117388a7525a8202b821a3945bc3237af95,2026-05-05,2026-05,Tuesday,Merge pull request #13 from Ritik574-coder/dbt_branch,13,1,Ritik574-coder,dbt_branch
3798cac3191b240755c7dc2eb7938cdf262cc426,2026-05-04,2026-05,Monday,Merge pull request #12 from Ritik574-coder/dbt_branch,12,1,Ritik574-coder,dbt_branch
897dbfb0ef7a373eae84c4e4417e501cd7130b67,2026-05-04,2026-05,Monday,Merge pull request #11 from Ritik574-coder/dbt_branch,11,1,Ritik574-coder,dbt_branch
755ab5ab731c0e6de5512c381bd6c7512555797e,2026-05-04,2026-05,Monday,Merge pull request #10 from Ritik574-coder/dbt_branch,10,1,Ritik574-coder,dbt_branch
39cb160a198e188dbf2cf4c206c8cc57928ac798,2026-05-03,2026-05,Sunday,Merge pull request #9 from Ritik574-coder/dbt_branch,9,1,Ritik574-coder,dbt_branch
eb2bd106995782a3f1f184dbae7c91f630820b2a,2026-05-03,2026-05,Sunday,Merge pull request #8 from Ritik574-coder/dbt_branch,8,1,Ritik574-coder,dbt_branch
cb939cd240dada445e72dae5ce13653107c76225,2026-05-02,2026-05,Saturday,Merge pull request #7 from Ritik574-coder/dbt_branch,7,1,Ritik574-coder,dbt_branch
2f2bcbe7599268689594c3aa685aac1d1cd96c2e,2026-05-01,2026-05,Friday,Merge pull request #6 from Ritik574-coder/dbt_branch,6,1,Ritik574-coder,dbt_branch
11e6c003d1d248b02e3b6df1e6f54072401abdda,2026-05-01,2026-05,Friday,Merge pull request #5 from Ritik574-coder/dbt_branch,5,1,Ritik574-coder,dbt_branch
af2eeb060234abfc9bfdd6e8b541f5fa64b7eba4,2026-05-01,2026-05,Friday,Merge pull request #4 from Ritik574-coder/dbt_branch,4,1,Ritik574-coder,dbt_branch
78eb7d44d5a70673b4968bc0a18d29aba06f5b56,2026-05-01,2026-05,Friday,Merge pull request #3 from Ritik574-coder/dbt_branch,3,1,Ritik574-coder,dbt_branch
aa5c6d7494b16882cc5cc0292cc72cfa07b05e54,2026-05-01,2026-05,Friday,Merge pull request #2 from Ritik574-coder/dbt_branch,2,1,Ritik574-coder,dbt_branch
d11350b1302c3d0293013303a09701354ef2ac6e,2026-05-01,2026-05,Friday,Merge pull request #1 from Ritik574-coder/dbt_branch,1,1,Ritik574-coder,dbt_branch
Loading