# PowerShell 7.x - قسمت یازدهم - یک مثال

به عنوان یک تمرین میخواهیم یک پروژه گیت ساده را به صورت زیر visualise کنیم: برای تولید چنین نموداری از میتوانیم Mermaid استفاده کنیم. یکی از انواع دیاگرام‌هایی را که پشتیبانی میکند، Gitgraph میباشد. د

- Published: 2023-04-05
- Language: fa
- Tags: DNTips
- Canonical: https://sirwan.info/blog/fa/dntips-3466

---

> این نوشته نخستین بار در [دات‌نت تیپس](https://www.dntips.ir/post/3466) منتشر شده است.

<div class="postBody">به عنوان یک تمرین میخواهیم یک پروژه گیت ساده را به صورت زیر visualise کنیم:  <div> <br/> <div> <div> <p style="margin-left: auto; margin-right: auto;"> <img src="/img/dntips/b3aebcb8980fe02adc18.jpg" style="display: block; margin-left: auto; margin-right: auto; cursor: default; height: 358px;"/> </p> <p style="margin-left: auto; margin-right: auto;"> <br/> </p> <p style="margin-left: auto; margin-right: auto;">برای تولید چنین نموداری از میتوانیم <a href="https://mermaid.js.org/">Mermaid</a> استفاده کنیم. یکی از انواع دیاگرام‌هایی را که پشتیبانی میکند، <a href="https://mermaid.js.org/syntax/gitgraph.html">Gitgraph</a> میباشد. دیاگرام‌ها در Mermaid با کمک یک DSL ساخته میشوند. سینکس آن نیز خیلی ساده است؛ ابتدا نوع دیاگرامی را که میخواهیم ترسیم کنیم، تعیین میکنیم و سپس محتویات را براساس نوع دیاگرام، تعیین میکنیم. به عنوان مثال برای Gitgraph سینتکس آن به این صورت است:  <br/> </p> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="CSharp" name="code">gitGraph&#10;   commit&#10;   commit&#10;   branch develop&#10;   checkout develop&#10;   commit&#10;   commit&#10;   checkout main&#10;   merge develop&#10;   commit&#10;   commit</pre>
 </div> <p style="margin-left: auto; margin-right: auto;">در ساختار فوق ابتدا دو کامیت بر روی برنچ اصلی (main) انجام شده‌است؛ سپس یک برنچ جدید را با نام develop، ایجاده کرده‌ایم و بلافاصله به آن checkout کرده‌ایم. در ادامه تعدادی کامیت را بر روی این برنچ انجام داده و در نهایت برنچ موردنظر را بر روی main، مرج کرده‌ایم. در نهایت نیز دو کامیت دیگر را بر روی main ایجاد کرده‌ایم. تعریف فوق، منجر به ساخت چنین نموداری خواهد شد:  <br/> </p> <p style="margin-left: auto; margin-right: auto;"> <img src="/img/dntips/12e2dd05cfdf5cfb55dd.jpg" style="display: block; margin-left: auto; margin-right: auto; cursor: default; height: 315px;"/> </p> <p style="margin-left: auto; margin-right: auto;"> <br/> </p> <p style="margin-left: auto; margin-right: auto;">از <a href="https://mermaid.live/">ادیتور آنلاین</a> Mermaid نیز میتوانید برای تست سینکس استفاده کنید. در ادامه میخواهیم با کمک PowerShell، از روی یک پروژه‌ی گیت، DSL موردنیاز برای ساخت دیاگرام را ایجاد کنیم. برای اینکار ابتدا توسط تابع زیر یک پروژه‌ی گیت را با تعدادی فایل نمونه ایجاد خواهیم کرد:  <br/> </p> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="CSharp" name="code">Function New-RandomRepo {&#10;    Function RandomFiles($branch = "main") {&#10;        1..3 | ForEach-Object {&#10;            New-Item -ItemType File -Name "file_$($_).txt"&#10;            Set-Content -Path "file_$($_).txt" -Value "This is file $($_) on branch $branch"&#10;            git add .&#10;            git commit -m "Commit $($_) on branch $branch"&#10;        }&#10;    }&#10;    Set-Location ~/Desktop&#10;    New-Item -ItemType Directory "random_git_repo"&#10;    Set-Location "random_git_repo"&#10;    git init -b main&#10;    Write-Output "This is the main branch" | Set-Content -Path "main.txt"&#10;    git add .&#10;    git commit -m "Initial commit"&#10;    1..3 | ForEach-Object { &#10;        git checkout -b "branch_$($_)"&#10;        RandomFiles "branch_$($_)"&#10;        git checkout main&#10;    }&#10;}</pre>
 </div> <p style="margin-left: auto; margin-right: auto;">در ادامه تابع New-GitRepoDiagram را برای تولید ساختار مورد نیاز نوشته‌ایم:  <br/> </p> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="CSharp" name="code">Function New-GitRepoDiagram {&#10;    $commitIds = @()&#10;    $branches = git branch | ForEach-Object {&#10;        $default = $false&#10;        $activeBranch = git symbolic-ref --short HEAD&#10;        $currentBranch = ($_.Replace("* ", " ")).Trim()&#10;        if ($currentBranch -eq $activeBranch) {&#10;            $default = $true&#10;        }&#10;        @{&#10;            name         = $currentBranch&#10;            isMainBranch = $default&#10;        } | ConvertTo-Json&#10;    } | ConvertFrom-Json&#10;    &#10;    $defaultBranch = $branches | Where-Object { $_.isMainBranch -eq $true } | Select-Object -ExpandProperty name&#10;    $mermaidFile = "%%{init: { 'gitGraph': {'mainBranchName': '$defaultBranch' } } }%%" + [Environment]::NewLine&#10;    $mermaidFile += 'gitGraph' + [Environment]::NewLine&#10;&#10;    foreach ($branch in ($branches | Sort-Object -Property isMainBranch -Descending)) {&#10;        $name = $branch.name&#10;        $notIncludeTheMainCommits = $name -ne $defaultBranch ? "--not $(git merge-base $defaultBranch $name)" : ""&#10;        $notIncludeTheMainCommits&#10;        $logs = git log --pretty=format:'{"commit": "%h", "author": "%an", "message": "%s"}' --reverse $name | ConvertFrom-Json&#10;        if ($name -ne $defaultBranch) {&#10;            $mermaidFile += '   branch "$name"'.Replace('$name', $name) + [Environment]::NewLine&#10;        }&#10;        foreach ($log in $logs) {&#10;            $commit = $log.commit&#10;            if ($commitIds -contains $commit) {&#10;                continue&#10;            }&#10;            $commitToAdd = '   commit id: "$commit"'.Replace('$commit', $commit) + [Environment]::NewLine&#10;            $mermaidFile += $commitToAdd&#10;            $commitIds += $commit&#10;        }&#10;        if ($name -ne $defaultBranch) {&#10;            $mermaidFile += '   checkout main' + [Environment]::NewLine&#10;        }&#10;    }&#10;    Write-Host $mermaidFile&#10;}</pre>
 </div> <p style="margin-left: auto; margin-right: auto;"> <b>توضیحات:</b> </p> <p style="margin-left: auto; margin-right: auto;"> </p> <ul> <li>در تابع فوق، ابتدا یک آرایه‌ی خالی برای ذخیره‌ی کامیت آی‌دی‌ها، اضافه شده؛ از این آرایه برای جلوگیری از اضافه شدن کامیت تکراری در هر برنچ استفاده شده‌است.</li> <li>سپس با کمک دستور git branch، لیست تمام برنچ‌ها، دریافت شده‌است (همانطور که در قسمت قبل بررسی شد <a href="/blog/fa/dntips-3465/">+</a>).</li> <li>برای هر برنچ، تابع تعیین میکند که آیا برنچ جاری است یا خیر. اینکار با کمک دستور git symbolic-ref انجام شده‌است.</li> <li>در ادامه متغیر mermaidFile$ برای ایجاد یک گراف جدید Git مقداردهی میشود. در اینجا نام برنچ اصلی برابر با نام برنچ پیش‌فرض، تنظیم می‌شود.</li> <li>سپس لیست کامیت‌های هر برنچ را با کمک دستور git log (همان سینتکسی که در قسمت‌های قبل بررسی شد <a href="/blog/fa/dntips-3464/">+</a>) استخراج میکنیم.</li> <li>و در نهایت به ازای هر کامیت، یک commit id تولید کرده‌ایم.</li> </ul> <p style="margin-left: auto; margin-right: auto;">با فراخوانی تابع فوق، اینچنین ساختاری برایمان تولید خواهد شد:  </p> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="CSharp" name="code">%%{init: { 'gitGraph': {'mainBranchName': 'main' } } }%%&#10;gitGraph&#10;   commit id: "765100f"&#10;   branch "branch_1"&#10;   commit id: "c88c441"&#10;   commit id: "44149d9"&#10;   commit id: "a660fe3"&#10;   checkout main&#10;   branch "branch_2"&#10;   commit id: "2dcb572"&#10;   commit id: "b043ad1"&#10;   commit id: "92cafc0"&#10;   checkout main&#10;   branch "branch_3"&#10;   commit id: "559e381"&#10;   commit id: "f72957f"&#10;   commit id: "c066e72"&#10;   checkout main</pre>
 </div> <p style="margin-left: auto; margin-right: auto;">خروجی فوق دقیقاً دیاگرامی است که در ابتدای مطلب نشان داده شد:</p> <p style="margin-left: auto; margin-right: auto;"> <img src="/img/dntips/2e605401969773b20957.jpg" style="display: block; margin-left: auto; margin-right: auto; cursor: default; height: 616px;"/> </p> </div> </div> </div></div>
