اگر برنامه نویسی هستید که تازه با سیستم گیت آشنا شدهاید و روی پروژه ای کار میکنید که روی این سیستم کنترل نسخه (version control) است. ممکن است وقتی دارید با خیال راحت عملیات merge یا pull را انجام میدهید به پیام ناخوشایند Conflict برخورد کنید. خیلی از تازه کارها در این لحظه دچار اضطراب و استرس می شوند که الان چه مشکلی پیش آمده است و یا کجای پروژه را خراب کرده ام. در این مطلب به شما می گویم که چگونه با conflict مواجه شوید و آن را مدیریت کنید.
در ابتدای کار بدانید که conflict اصلا یک خطا یا error نیست. این یک پدیده طبیعی در کارها و پروژه های تیمی است و یک بخش عادی در فرایند گیت به حساب می آید.
تداخل (conflict) چیست؟
به زبان خیلی ساده conflict به این معنی است که گیت با دو تغییر متفاوت در یک فایل مواجه شده است و نمی داند که کدام تغییر را حفظ کند و کدام را دور بریزد. به خاطر همین از برنامه نویس یا شخصی که در حال ادغام دو نسخه از پروژه است می خواهد که خودش تصمیم بگیرد که این تداخل تغییرات را مدیریت کند. یعنی شما به گیت کمک کنید که تصمیم بگیرد با تغییرات چه کند.
به عبارت دیگر وقتی که شما یا یکی دیگر از اعضای تیم در دو branch(شاخه) یک قسمت مشابه از یک فایل را تغییر داده باشید و بخواهید این دو برنچ را با هم ادغام کنید conflict پیش خواهد آمد. زیرا که گیت نمی داند که کدام یک از این تغییرات را نگهداری کند.
گیت نمی داند که
تغییر شما مهم تر است؟
تغییر هم تیمی شما مهم تر است؟
هر دو بخش از تغییرات باید با هم ترکیب شده و نگهداری شوند؟
در این حالت گیت برای جلوگیری از خرابی کدهای شما فرایند merge را متوقف می کند و از شما می خواهد که این دو تا نسخه را بازبینی کنید و خودتان تصمیم بگیرید که کدام را لازم دارید. به عبارت دیگر : رفیق، من اینجا گیر کردم. این دو تا نسخه از کد با هم تداخل دارن. لطفاً خودت بیا ببین کدوم رو لازم داری.
کدهای عجیبی که گیت هنگام conflict به کد شما اضافه می کند.
وقتی که در یک فایل conflict پیش می آید گیت فایل مورد نظر را با یک سری نشانگر (marker) عجیب علامت گذاری می کند. شاید دیدن این نشانگر ها برای اولین بار حس خوبی به شما ندهد و فکر کنید که فایل پروژه شما توسط خود گیت خراب شده و به هم ریخته است ولی اگر بلد باشید با این marker ها کار کنید راحت می توانید فایل خود را درست کنید. برای مثال در یک یا چند قسمت از فایل شما علامت های زیر ممکن است که نوشته شده باشد.
<<<<<<< HEAD
این کدی هست که شما توی برنچ فعلیتون (HEAD) نوشتید.
=======
این کدی هست که از اون یکی برنچ (مثلاً feature-branch) داره میاد.
>>>>>>> feature-branch
بیاید این عبارت ها را بررسی کنیم.
خط <<<<<<< HEAD:این خط به شما می گوید که این بخش از کانفلیکت از اینجا شروع می شود و تغییرات شما که در برنچ جاری انجام داده اید از اینجا شروع می شود. (برنچ مقصد)
خط =======: این خط جدا کننده است. هر عبارت و کدی که قبل از این خط قرار دارد تا خط HEAD مربوط به برنچ مقصد است. و از این خط به بعد کدها و عبارات مربوط به برنچ دوم است.
خط >>>>>>> feature-branch نشانگر پایان بخش تغییراتی است که در برنچ feature-branch که همان برنچ دوم است می باشد. به عبارت دیگر این خط می گوید که تغییرات برنچ دوم اینجا تمام می شود.
حال وظیفه شما برای حل تداخل ها این است که بین این دو دسته کد که بین این علامت ها قرار گرفته اند تصمیم بگیرید که کدام را نگهداری کنید و کدام را حذف کنید و کد نهایی به چه شکل باشد.
راهنمای قدم به قدم حل کانفلیکت (روش دستی)
خب نیاز است که کانفلیکت را برطرف کنید. برای این کار قدم به قدم توضیح می دهیم که چگونه این کار باید انجام شود. فرض کنید که شما دستور ادغام یک برنچ را در برنچ جاری خود به شکل کد زیر زده اید.
git merge feature-xy
هنگام ادغام گیت به شما پیام کانفلیکت می دهد. که باید قدم به قدم کارهای زیر را انجام دهید.
- یک بار وضعیت را با دستور git status چک می کنیم. با این دستور گیت به شما می گوید که دقیقا کدام فایل ها کانفلیکت دارند.
git status - فایل های کانفلیکت دار را در ادیتور مورد علاقه خودتان باز کنید. (notepad , vscode , یا هر IDE که با آن کار می کنید.)
- تصمیم بگیرید و ویرایش کنید. یعنی دنبال همان نشانگر هایی که گفتیم بگردید و تصمیم بگیرید که یکی از راه های پایین را انتخاب کنید.
1. نگه داشتن تغییرات خودتان (HEAD): کدهای بین <<<<<<< HEAD و ======= رو نگه میدارید و بقیه (از ======= تا >>>>>>>) رو پاک میکنید.
2. قبول کردن تغییرات ورودی (Incoming): کدهای بین ======= و >>>>>>> رو نگه میدارید و کدهای بخش HEAD رو پاک میکنید.
3. ترکیب هر دو: گاهی وقت ها شما به هر دو قطعه کد نیاز دارید. مثلاً شما یک متغیر اضافه کردید و همتیمی شما یک متغیر دیگر. در این حالت، شما هر دو قطعه کد را نگه میدارید و فقط اون سه تا نشانگر گیت (<<<، ===، >>>) رو پاک میکنید.
مهم: هدف نهایی این است که فایل به شکلی باشد که از نظر منطقی درست باشد و هی یک از نشانگر های گیت در داخل آن نباشد. - ایندکس کردن فایل کانفلیکت دار: بعد از حل همه کانفلیکت های یک فایل آن را ذخیره کرده و در این مرحله با استفاده از دستور git add فایل را ایندکس می کیم.
git add [filename] - کامیت کردن: قدم آخر ذخیره کردن نتیجه کار شما در ریپازیتوری است که با دستور git commit انجام خواهد شد و تغییرات در تاریخچه گیت ثبت خواهند شد.
git commit
در این مرحله لازم است که یک پیام یادداشت در باره ی تغییرات بنویسید و خود گیت یک توضیح پیش فرض برای شما آماده کرده است آن را می توانید ذخیره کنید و کار تمام است.
حل کانفلیکت با ابزارهایی مانند Vs-code
با این که اصول برطرف کردن کانفلیکت همان است که بالاتر گفتیم ولی ابزارهایی مانند vscode این کار را راحت تر و سریع تر انجام می دهند. وقتی در این ابزارها فایل کانفلیکت دار را باز می کنید به صورت اتوماتیک جاهایی که کانفلیکت پیش آمده است را تشخیص داده و لیست می کند و بالای کدهای درگیر چند تا گزینه به شما نمایش می دهد که عبارتند از:
- Accept Current Change: یعنی فقط تغییرات من (HEAD) رو نگه دار.
- Accept Incoming Change: یعنی فقط تغییرات اون یکی برنچ رو قبول کن.
- Accept Both Changes:هر دو تا قطعه کد را پشت سر هم می آورد.
- Compare Changes: یه نمای مقایسهای قشنگ به شما می دهد.
شما با انتخاب هرکدام از این گزینه ها دقیقا همان کاری را انجام می دهید که در حالت دستی انجام می دادید ولی این بار فقط با یک کلیک کار تمام می شود. بعد از حل کانفلیکت ها مانند روش دستی اعمال ایندکس و کامیت را انجام بدهید.
دقت داشته باشید که کسی که در حال برطرف کردن کانفلیکت ها است کسی باید باشد که به هر دو فایل مسلط باشد و به کل پروژه اشراف داشته باشد که باعث دوباره کاری و خرابکاری نشود. کسی که اطلاعات کافی از تغییرات انجام شده و روند پروژه نداشته باشد ممکن است هنگام حل کانفلیکت فایل ها را به جایی بدتر از قبل ببرد و مشکلات بزرگتری ایجاد کند.
چطور تا حد ممکن از کانفلیکت جلوگیری کنیم؟
گفتیم که کانفلیکت ممکن است در روند پروژه پیش بیاید و مفهوم ترسناکی نیست اما حل کانفلیکت نیاز به زمان دارد و قطعا کسی دوست ندارد که وقتش را صرف حل کردن کانفلیکت ها کند اگر بداند که می شود از آن جلو گیری کرد یا آن را به حداقل رساند. در ادامه راه هایی را توضیح داده ایم که باعث می شود رخ دادن کانفلیکت به حداقل برسد.
۱. زود به زود pull یا rebase کنید.
سعی کنید هر روز صبح یا قبل از شروع توسعه قابلیت جدید آخرین تغییرات برنچ اصلی را دریافت کنید و با پروژه خودتان ادغام کنید.
۲. برنچ ها را کوچک نگه دارید.
سعی نکنید که چندین کار متختلف را داخل یک برنچ انجام بدهید. هر قابلیت یا تسک (task) کوچک باید برنچ خودش را داشته باشد. در این صورت ادغام آنها خیلی راحت تر خواهد بود.
۳.با اعضای تیم صحبت کنید
این بسیار مهم است بدانید که هم تیمی شما هم روی همان فایلی کار می کند که شما هم کار می کنید. اگر از همدیگر خبر داشته باشید و از روند کار هرکدام مطلع باشید می توانید با هم هماهنگ شوید و از تداخل ها پیشگیری کنید.
جمع بندی:
تداخل (conflict) هیولای ترسناکی نیست. کانفلیکت فقط یک دستیار است که وقتی در ادغام پروژه گیر می کند از شما کمک می خواهد و از شما سوال می پرسد.
مراحل حل کانفلیکت ساده است و عبارتند از:
۱. مشاهده git status
۲. باز کردن فایل تداخل دار
۳. تصمیم گیری در مورد تداخل
۴. پاک کردن نشانگر گیت
۵. git add
6. git commit
نظرات کاربران (0)