آموزش گیت – قسمت یازدهم

نویسنده : سید ایوب کوکبی ۲۷ اردیبهشت ۱۳۹۸
آموزش گیت - قسمت یازدهم

در درس‌های قبلی گیت با گردش کار متمرکز و integrator به کمک شاخه‌ها آشنا شدید. مثلاً توسعه‌دهنده کل شاخه را برای ما ارسال می‌کرد تا با پروژه ادغام کنیم. با این حال راه‌های دیگری نیز برای مشارکت برنامه‌نویسان در پروژه هست که یکی از آن‌ها استفاده از patch بوده که در ادامۀ متن از معادل فینگلیش آن یعنی «پَچ» استفاده خواهیم کرد.

یک فایل پچ حاوی مجموعه‌ای از تغییرات (یک کامیت) است که می‌تواند روی هر شاخه‌ای اعمال شود. گردش کار پچ (Patch Workflow) چیزی شبیه همان interactive rebase است با این تفاوت که به راحتی می‌توانید پچ‌ها را با سایر توسعه‌دهندگان به اشتراک بگذارید. این روش از درجۀ اهمیت شاخه‌ها کاسته و اجازۀ کنترل بیشتری به مدیر پروژه می‌دهد. مشارکت در سطح کامیت‌ها، مزیتِ فهمِ مکانیزم ذخیره‌سازی تاریخچۀ پروژه در گیت را نیز داراست.

تغییر صفحۀ pink (ماری)

ابتدا خودمان را جای ماری می‌گذاریم. ماری از صفحۀ صورتی اضافه شده توسط جان خوشش نیامده و قصد دارد اندکی آن را تغییر دهد:

cd /path/to/marys-repo
git checkout -b pink-page

اعمال تغییرات در شاخه‌ای مجزا، نه‌تنها این توانایی را به ماری می‌دهد تا در محیطی ایزوله پروژه را توسعه دهد بلکه ساخت دنباله‌ای از پچ‌ها را هم ساده می‌کند. خطوط پایین را در صفحۀ pink.html پیدا کنید:

<p>Pink is <span style="color: #F0F">girly,
flirty and fun</span>!</p>

و تغییرشان دهید به:

<p>Only <span style="color: #F0F">real men</span> wear pink!</p>

مثل یک آپدیت معمولی، استیج و کامیت کنید:

git commit -a -m "Change pink to a manly color"

توجه داشته باشید که روال توسعۀ پروژه برای ماری هیچ تغییری نکرده و دقیقاً مانند گذشته است. پچ مثل گردش‌کار متمرکز و integrator، راهی برای اشتراک تغییرات با سایر توسعه‌دهندگان است. این موضوع هیچ تاثیری روی مفاهیم پایۀ گیت که در ابتدای این سری آموزشی توضیح دادیم ندارد.

ساخت یک پچ (ماری)

ماری می‌تواند با دستور git format-patch از کامیتی که جدیداً ساخته یک پچ بسازد:

git format-patch master

با اجرای این دستور، فایلی به نام ۰۰۰۱Change-pink-to-a-manly-color.patch ساخته می‌شود که حاوی اطلاعات کافی برای ساخت مجدد کامیت مرحلۀ قبل است. نام فایل همان پیام کامیت است که با خط تیره از هم جدا شده و در ابتدای آن به صورت خودکار شمارۀ پچ افزوده شده است. پسوند فایل patch است که با مراجعه به فولدر پروژه خواهید دید. پارامتر master در انتهای دستور به گیت می‌گوید به ازای هر کامیتی که در شاخۀ جاری هست ولی در شاخۀ مستر نیست (مسترِ خودمان) یک پچ مستقل ایجاد کن.

فایل پچ را در در یک ادیتور متنی باز کنید. بالای فایل همانند ایمیل دقیقاً مشخص شده که این پچ از سوی چه کسی ارسال شده است؛ چه زمانی ارسال شده و موضوع نامه چیست. این اطلاعات کمک می‌کند تا پچ را به سادگی برای دیگران ارسال کنیم. در ادامۀ فایل، چیزهای دیگری هم وجود دارد:

index 98e10a1..828dd1a 100644
--- a/pink.html
+++ b/pink.html
@@ -۷,۸ +۷,۷ @@
 </head>
<body>
   <h1 style="color: #F0F">The Pink Page</h1>
-  <p>Pink is <span style="color: #F0F">girly,
-  flirty and fun</span>!</p>
+  <p>Only <span style="color: #F0F">real men</span> wear pink!</p>
 
   <p><a href="index.html">Return to home page</a></p>
 </body>

این فرمت خاص مربوط به خروجی دستور diff است. دستور diff تفاوت بین دو نسخه از فایل را به طور مفصل نشان می‌دهد و چیزی که در بالا می‌بینید خروجی دستور فوق است. در اینجا تفاوت فایل pink.html در کامیت ۹۸e10a1 و ۸۲۸dd1a نشان داده شده که البته برای شما آیدی کامیت‌ها متفاوت است.

بخوانید  آموزش گیت - قسمت هفتم

اعداد -۷,۸ +۷,۷ خطوطی که تحت تأثیر پچ قرار می‌گیرند را نشان می‌دهد و مابقی فایل، محتویات قبل و بعد از تغییر را نشان می‌دهد. قسمت‌های مشکی دست نخورده باقی می‌مانند. خطوط قرمز که با خط تیره مشخص شده قسمت‌هایی که حذف می‌شوند را نشان می‌دهد و نهایتاً خطوط سبز با علامت بعلاوه بیانگر مواردی است که به فایل اضافه خواهند شد. فعلاً به این فایل نیازی نداریم. حذفش کنید. بعداً دوباره می‌سازیم؛ هدف فقط آشنایی بود.

افزودن یک بلاک به فایل pink.html (ماری)

قبل از آموزش تبدیل پچ به کامیت، ماری اسنپ‌شات دیگری اضافه می‌کند. در فایل pink.html کدهای پایین را بعد از تگ meta قرار دهید.

<style>
  div {
    width: 300px;
    height: 50px;
  }
</style>

و خط پایین را بعد از عبارت Only real men wear pink اضافه کنید:

<div style="background-color: #F0F"></div>

نهایتاً اسنپ‌شات جدید را استیج و کامیت کنید:

git commit -a -m "Add a pink block of color"

مخزن ماری اکنون با دو کامیت ازشاخۀ origin/master (شاخۀ مستر در مخزن رسمی پروژه) جلو افتاده است:

افزودن دو کامیت به شاخۀ pink-page

ساخت پچ از کل شاخه (ماری)

ماری می‌تواند از همان دستور قبلی برای ساخت پچ از تمام کامیت‌های شاخۀ pink-page استفاده کند؛ به این صورت:

git format-patch master

پچ اولی دقیقاً مثل پچ قبلی است. علاوه بر این یک پچ دیگر نیز داریم به نام ۰۰۰۲Add-a-pink-block-of-color.patch که حاوی کامیت دومی است که اخیراً اضافه کردیم. اینجا هم نام کامیت دوم برای فایل انتخاب شده است. محتوای پچ دوم:

index 828dd1a..2713b10 100644
--- a/pink.html
+++ b/pink.html
@@ -۴,۱۰ +۴,۱۷ @@
   <title>The Pink Page</title>
   <link rel="stylesheet" href="style.css" />
   <meta charset="utf-8" />
+  <style>
+    div {
+      width: 300px;
+      height: 50px;
+    }
+  </style>
 </head>
 <body>
<h1 style="color: #F0F">The Pink Page</h1>
   <p>Only <span style="color: #F0F">real men</span> wear pink!</p>
+  <div style="background-color: #F0F"></div>
 
   <p><a href="index.html">Return to home page</a></p>
 </body>

قالب این کامیت هم مثل کامیت قبلی است. یک خط اضافه شده و همان یک خط را هم نشان می‌دهد. چون چیزی از فایل حذف نشده، خطوط قرمز نداریم. همانطور که می‌بینید محتوای پچ‌ها به راحتی تغییرات هر کامیت را منعکس می‌کنند.

ایمیل کردن پچ‌ها (ماری)

اکنون ماری مجموعه‌ای از پچ‌های آماده در اختیار دارد که می‌تواند به مدیر پروژه (یعنی ما) ارسال کند. در گردش‌کارهای مرسوم patch این کار با ایمیل کردن پچ اتفاق می‌افتد که به یکی از روش‌های زیر انجام می‌شود:

  • کپی و پیستِ محتوای پچ و ارسال آن با ایمیل. در صورت استفاده از این روش، ماری حتماً باید مطمئن شود که کلاینت ایمیلی او whitespace ها را تغییر نمی‌دهد و چیزی به آن اضافه نمی‌کند؛
  • ایمیل کردن پچ در قالب یک فایل ضمیمه؛
  • استفاده از دستور git send-email و مشخص کردن فایل یا فولدری که می‌خواهید ایمیل شود. مثلاً . git send-email تمام پچ‌ها در فولدر جاری را ارسال می‌کند. نقطۀ پایانی به تمام فایل‌ها اشاره می‌کند که برای دستور git send-email منظور همۀ پچ‌هاست. برای استفاده از این دستور نیازمند پیکربند گیت هستید که توضیحات مفصل آن را می‌توانید در مستدان رسمی گیت مطالعه کنید.
بخوانید  آمار جالبی از موبایل در سال 2018

نکتۀ اصلی اینجاست که در گردش‌کار patch باید به طریقی پچ‌ها را به دست شخصی که می‌خواهیم مخزن او را بروز کنیم ارسال نماییم. حالا می‌خواهد با ایمیل باشد، با فلش مموری، تلگرام یا هر راه دیگری. در مثال ما چون همۀ توسعه‌دهنده‌ها روی سیستم ما قرار دارند (در قالب فولدرهای جدا، ماری، جان و خودمان) کافی است تا فایل‌های پچ را به مقصد یعنی my-git-repo کپی کنیم.

اعمال پچ‌ها (شما)

بعد از کپی دو پچ ساخته شده توسط ماری به فولدر my-git-repo با دستور جدید git am می‌توانیم کامیت‌های ماری را به مخزن خود اضافه کنیم:

cd ../my-git-repo
git checkout -b patch-integration
git am < 0001-Change-pink-to-a-manly-color.patch
git log master..HEAD --stat

اگر دقت کرده باشید مشاهده می‌کنید که ادغام در شاخۀ جدیدی صورت گرفته است تا احیاناً در صورت بروز مشکل، شاخۀ اصلی پروژه یعنی مستر را خراب نکنیم. سپس با دستور git am از پچ وارد شده یک کامیت استخراج و به شاخه‌ای که تعریف کرده‌ایم اضافه می‌کنیم. اکنون به لاگ دستور می‌دهیم که کامیت‌های موجود در شاخه‌ای که HEAD به آن اشاره می‌کند (patch-integration ) ولی در مستر موجود نیست را نمایش دهد و با فلگ stat– درخواست نمایش جزئیات را هم می‌دهیم.

همین کار را برای پچ دوم هم انجام می‌دهیم:

git am < 0002-Add-a-pink-block-of-color.patch
git log master..HEAD --stat

دستور گیت طوری تنظیم شده که از ورودی استاندارد (standard input) بخواند و کاراکتر > نیز برای وارد کردن یک فایل به ورودی استاندارد به کار می‌رود. این کاراکتر مختص گیت نیست بلکه در خط فرمان ویندوز نیز به کار می‌رود. بعد از اعمال پچ دوم، اکنون شاخۀ integration-patch دقیقاً مشابه شاخۀ pink-page ماری شده است. ما دقیقاً پچ‌ها را به همان ترتیبی که ماری ساخته اعمال کرده‌ایم ولی این کار ضروری نیست. تنها کاری که پچ انجام می‌دهد ایزوله کردن یک کامیت و ارسال آن به روش‌های دیگر است.

ادغام پچ‌ها در شاخۀ مستر (شما)

دوباره به نقطه‌ای رسیدیم که باید شاخه‌ای فرعی را با شاخۀ اصلی پروژه ترکیب کنیم. این کار را به خوبی بلدید:

git checkout master
git merge patch-integration
git branch -d patch-integration
git clean -f
git push origin master

اکنون آپدیت ماری به صورت کامل به مخزن رسمی پروژه ارسال شده است و با دستور push آخرین نسخۀ پروژه را در اختیار سایر توسعه‌دهندگان گذاشته‌ایم. بنابراین دیگر نیازی به فایل‌های پچ نداریم پس با دستور git clean آن‌ها را پاک می‌کنیم. به خاطر دارید که این دستور تمام فایل‌های untracked را از working directory حذف می‌کند. فلگ f- می‌گوید که همۀ فایل‌های untracked را حذف کن. و اگر تمایل به حذف فولدرهای اضافه داشتید، فلگ d- را هم اضافه کنید. git clean -f -d

بخوانید  آشنایی با گیت (git) - بخش دوم

آپدیت مخزن ماری (ماری)

ماری ممکن است بخواهد شاخۀ pink-page را مستقیماً با شاخۀ مسترش ترکیب کند؛ ولی این کار اشتباه است چون در درس قبلی آموختید که شاخۀ مستر باید آخرین تغییرات شاخۀ مستر در مخزن رسمی را دنبال کند. در صورتی که هر کسی بخواهد شاخۀ مستر خود را تغییر دهد و سپس به مخزن پوش کند، تداخل به وجود می‌آید.

cd ../marys-repo
git checkout master
git fetch origin
git rebase origin/master
git branch -D pink-page
git clean -f

پچ‌ها روشی قراردادی برای اشتراک کامیت‌ها بین توسعه‌دهندگان است ولی باز هم در این گردش‌کار به یک مخزن رسمی که ماحصل تغییرات برنامه‌نویسان در آن نگه‌داری می‌شود نیاز خواهیم داشت. چه اتفاقی می‌افتاد اگر ماری تنها کسی نبود که پچ ارسال می‌کرد؟ ممکن بود پچ‌های مختلفی را اعمال می‌کردیم یا پچ‌های ماری را با ترتیب متفاوتی اعمال می‌کردیم. اما اگر ماری خودش شاخۀ pink-page را با شاخۀ master خود ترکیب می‌کرد همۀ این بروزرسانی‌ها از بین می‌رفت. با در نظر گرفتن ملاحظات بیان شده، گردش کار patch مطابق تصویر زیر خواهد بود:

Patch workflow در گیت
Patch workflow

جمع‌بندی

با اینکه مخازن ریموت راه مناسبی برای اشتراک کلِ شاخه‌ها هستند، پچ‌ها راهی برای ارسال کامیت‌های مشخص به سایر دولوپرها است. توجه داشته باشید که پچ‌ها معمولاً به صاحب اصلی پروژه (main project maintainer) ارسال می‌شود تا با پروژه ادغام کند. چون تاریخچۀ سایر افراد متفاوت است و ممکن است اعمال پچ به ترتیبی غیر از ترتیب درست، کدهای آن‌ها را دچار مشکل کند.

از جهات بسیاری، پچ‌ها نسبت به گردش‌کار integrator راهی ساده‌تر برای پذیرفتن مشارکت سایرین است. در این روش، مالک رسمی پروژه فقط به مخزن عمومی خودش نیاز دارد و هیچ نیازی به بررسی مخزن دیگران ندارد. از نقطه‌نظر مالک پروژه، پچ دقیقاً همان امنیت گردش‌کار integrator را فراهم می‌کند چون کماکان نیازی نیست که به سایر افراد دسترسی به مخزن رسمی را بدهد. افزون بر اینکه او دیگر نیازی به تحت نظر گرفتن مخازن ریموت دیگران نیز ندارد. در واقع لازم نیست مخازن عمومی سایر افراد را برای بررسی تغییرات صورت گرفته بررسی کند. همۀ تغییرات مستقیماً در غالب پچ برای او ارسال می‌شود.

به عنوان یک توسعه‌دهنده، سعی کنید از پچ زمانی استفاده کنید که می‌خواهید باگ پروژه‌ای را برطرف کنید. بعد از تعمیر باگ می‌توانید تغییرات را در قالب یک پچ برای صاحب پروژه ارسال نمایید. برای تغییرات یکبار مصرف این‌چنینی ارسال پچ بهتر از ساخت یک مخزن عمومی است.

امیدواریم با توضیحات این درس بحث گردش‌کارها در گیت را به خوبی یاد گرفته باشید. اکنون با گردش‌کار متمرکز، integrator و patch آشنا هستید. در درس بعد شما را با دستورات بیشتری از گیت آشنا می‌کنیم.

چکیدۀ دستورات

  • <git format-patch <branch-name : ساخت پچ برای هر کامیتی که در شاخۀ جاری هست ولی در branch-name وجود ندارد. به جای نام شاخه می‌توانید آیدی آن را نیز استفاده کنید؛
  • <git am < <patch-file : اجرای پچ روی شاخل فعلی.

سید ایوب کوکبی

نویسنده و مترجم...

مطالب مرتبط

0 دیدگاه

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *