شاخهها در گیت
ساختن شاخهٔ موازی، جابهجایی بین شاخهها با switch، ادغام با merge و حل تعارض ادغام.
آنچه در این درس میآموزید
- بدانید شاخه در گیت چیست و چگونه در تاریخچه کار میکند
- شاخه بسازید، بین شاخهها جابهجا شوید و آنها را ادغام کنید
- تعارض ادغام را تشخیص دهید و حل کنید
فهرست مطالب
تا اینجا تاریخچهٔ پروژهٔ شما یک خط مستقیم بود. اما کار واقعی اینطور پیش نمیرود: وسط کار روی نسخهٔ پایدار، درخواست میآید که یک باگ فوری را درست کنید؛ یا میخواهید یک ایدهٔ آزمایشی را امتحان کنید بدون اینکه نسخهٔ سالم پروژه را خراب کنید. شاخهها (Branches) دقیقاً برای همین ساخته شدهاند: چند خط کاری موازی روی یک تاریخچهٔ مشترک.
شاخه دقیقاً چیست؟
در گیت هر کامیت یک شناسه دارد و «شاخه» چیزی نیست جز یک اشارهگر سبکوزن (پروندهٔ ۴۱ بایتی) به یکی از این کامیتها. شاخهٔ main پیشفرض پروژه است و HEAD هم اشارهگری است که میگوید شما الان روی کدام شاخه و کدام کامیت ایستادهاید. وقتی کامیت جدید میسازید، گیت شاخهٔ فعلی را به کامیت تازه جابهجا میکند؛ یعنی شاخه با شما رشد میکند.
چون شاخه فقط یک اشارهگر است، ساختنش در گیت تقریباً رایگان است — برخلاف خیلی از ابزارهای قدیمیتر که کپی کامل از کد میساختند.
ساخت و جابهجایی شاخه
git branch # list branches
git branch feature-login # create a new branch
git switch feature-login # switch to that branchنمونهٔ خروجی فرمان آخر:
Switched to branch 'feature-login'میتوانید هر دو کار را با یک فرمان انجام دهید:
git switch -c feature-loginنمونهٔ خروجی:
Switched to a new branch 'feature-login'اگر git status بزنید، میبینید گیت میگوید روی کدام شاخهاید. حالا هر کامیتی که بزنید فقط به feature-login اضافه میشود و main سر جای خودش میماند.
ادغام شاخهها: git merge
وقتی کار روی شاخه تمام شد، آن را به شاخهٔ اصلی برمیگردانید:
git switch main
git merge feature-loginاگر main از زمان ساختهشدن شاخه پیش نرفته باشد، گیت کاری ساده میکند که به آن «ادغام سریع» (Fast-forward) میگویند: فقط اشارهگر main را جلو میکشد. نمونهٔ خروجی:
Updating 3f2a1c9..7b8c9d0
Fast-forward
app.py | 1 +
1 file changed, 1 insertion(+)اما اگر هر دو شاخه کامیتهای تازه داشته باشند، گیت یک «کامیت ادغام» میسازد که دو خط تاریخچه را به هم وصل میکند. خروجی این حالت با جملهٔ Merge made by the 'ort' strategy. شروع میشود.
پس از ادغام، شاخهٔ کارتان دیگر لازم نیست؛ حذفش کنید:
git branch -d feature-loginنمونهٔ خروجی:
Deleted branch feature-login (was 7b8c9d0).حذف شاخه فقط اشارهگر را پاک میکند؛ کامیتها را اگر هنوز به آنها دسترسی هست، از دست نمیدهید. برای دیدن نقشهٔ شاخهها از git log --graph --oneline --all استفاده کنید.
تعارض ادغام: وقتی گیت نمیتواند تصمیم بگیرد
اگر دو شاخه «همان خط» از یک فایل را متفاوت تغییر داده باشند، گیت نمیداند کدام را میخواهید. در این حالت ادغام متوقف میشود:
Auto-merging app.py
CONFLICT (content): Merge conflict in app.py
Automatic merge failed; fix conflicts and then commit the result.فایلِ متضاد را باز کنید؛ گیت دو نسخه را با نشانگرهای مخصوص مشخص کرده است:
<<<<<<< HEAD
print("main version")
=======
print("feature version")
>>>>>>> feature-text- بین
<<<<<<< HEADو=======نسخهٔ شاخهٔ فعلی است. - بین
=======و>>>>>>>نسخهٔ شاخهٔ واردشده است.
کار شما این است که فایل را به شکل درستِ نهایی دستی ویرایش کنید — گاهی یکی از دو نسخه، گاهی ترکیبی از هر دو — و نشانگرهای <<<<<<<، ======= و >>>>>>> را کامل پاک کنید. بعد همان مسیر همیشگی:
git add app.py
git commit -m "Resolve merge conflict in app.py"git status تا زمانی که فایل متضاد حل نشده باشد، فایل را «both modified» نشان میدهد. تعارض خبر بد نیست؛ یعنی گیت از شما میپرسد و جایی حدس نمیزند.
تمرینها
تمرین
تمرین ۱ — شاخه بساز و ادغام کن
در مخزن تمرینهای درس قبل یک شاخه به نام greeting بسازید، در آن شاخه فایلی به نام hello.txt بسازید و کامیت کنید، به main برگردید و شاخه را ادغام کنید. در پایان با git log --graph --oneline --all نتیجه را ببینید.
# Write your commands hereنمایش راهحل
git switch -c greeting
echo "hi there" > hello.txt
git add hello.txt
git commit -m "Add greeting file"
git switch main
git merge greetingچون main در این مدت پیش نرفته، خروجی merge با Fast-forward است و فایل hello.txt حالا در main هم هست.
:::
تمرین
تمرین ۲ — عمداً تعارض بسازید
از دو شاخهٔ متفاوت شروع کنید: در شاخهٔ main سطر اول notes.txt را بنویسید «version from main» و کامیت کنید؛ سپس شاخهٔ notes-rewrite بسازید، همان سطر را «version from notes-rewrite» بگذارید و کامیت کنید. حالا در main دستور git merge notes-rewrite را بزنید، فایل را باز کنید، تعارض را به نفع نسخهٔ شاخهٔ تازه حل کنید و کامیت بزنید.
# Write your commands hereنمایش راهحل
echo "version from main" > notes.txt
git add notes.txt
git commit -m "Update notes on main"
git switch -c notes-rewrite
echo "version from notes-rewrite" > notes.txt
git add notes.txt
git commit -m "Rewrite notes"
git switch main
git merge notes-rewrite # stops with a CONFLICT message
# in notes.txt remove the conflict markers and keep only the line
# "version from notes-rewrite"
git add notes.txt
git commit -m "Resolve notes conflict"گیت ادغام را نیمهکاره رها کرده بود؛ شما فایل را ویرایش کردید و با add و commit ادغام را بستید. علامت «#» در دستورهای بالا فقط توضیح است و اجرا نمیشود.
:::
خلاصه
- شاخه فقط یک اشارهگر به یک کامیت است؛ ساختن و حذفش ارزان است.
git switch -c nameشاخه میسازد و میرود؛checkoutمعادل قدیمی آن است.git mergeشاخه را ادغام میکند؛ نتیجه یا fast-forward است یا کامیت ادغام.- در تعارض، فایل را دستی اصلاح، نشانگرها را پاک و با
addوcommitادغام را تمام کنید.
شاخههای واقعی پروژهها معمولاً برای دیگران هم قابلمشاهدهاند تا بتوانند روی همان کد بازبینی کنند. در درس بعدی گیت را به یک مخزن راه دور مثل گیتهاب وصل میکنیم و همین گردش کار گروهی را کامل میکنیم.