در این مقاله، میخواهیم به یکی از ویژگیهای بسیار مهم و قدرتمند گیت یعنی شاخهبندی (Branching) بپردازیم. چه یک توسعهدهنده انفرادی باشید که روی چندین ویژگی کار میکنید یا عضوی از یک تیم بزرگ که وظایف مختلفی دارند، شاخهبندی در گیت میتواند فرآیند کاری شما را روانتر و مؤثرتر کند.
در گیت، مفهوم Branch به شما اجازه میدهد از مسیر اصلی پروژه انشعاب بگیرید و ویژگیهای جدید را به صورت مستقل توسعه دهید یا آزمایش کنید. هر Branch مانند یک فضای کاری جداگانه است که از کد اصلی پروژه ایزوله میشود. این ویژگی به شما امکان میدهد بدون تأثیر بر کد پایدار، تغییرات ناپایدار را مدیریت کنید. Branchها به تیمها کمک میکنند تا همزمان روی چندین وظیفه کار کنند، بدون اینکه به شاخه اصلی (که معمولاً به نام master شناخته میشود) آسیب بزنند.
در گیت، Branchها بسیار سریع و سبک هستند. برخلاف سیستمهای قدیمیتر مثل Subversion که ایجاد Branch به کپی کامل پروژه منجر میشد، در گیت فقط یک اشارهگر به کامیتها ایجاد میشود. این اشارهگر به شما امکان میدهد به سرعت بین Branchها جابجا شوید. هر Branch مستقل از دیگری کار میکند، و تغییرات شما در Branchها بدون تأثیر بر پروژه اصلی انجام میشود. بنابراین، گیت با استفاده از این روش، توسعه چندگانه و همزمان را بسیار سریع و کارآمد میکند.
فرض کنید یک باگ گزارش شده که باید رفع شود؛ برای جلوگیری از تغییرات روی کد اصلی، باید یک Branch جدید ایجاد کنید.
گام 1: ایجاد یک Branch جدید:
git branch bugfix
گام 2: لیست Branch ها:
git branch
گام 3: جابجایی به Branch جدید:
git switch bugfix git checkout bugfix
نامگذاری توصیفی Branchها، مثل bugfix/signup-form
، کمک میکند وظایف بهتر مدیریت شوند.
که برای تغییر نام Branch میتونیم از دستور زیر استفاده کنیم
git branch -m bugfux bugfix-sign
بعد از ایجاد Branch جدید برای رفع باگ، حالا باید تغییرات لازم را در فایلها اعمال کنیم. فرض کنید فایلی به نام audience.txt
دارید که میخواهید آن را ویرایش کنید. تغییرات ممکن است شامل اصلاح، اضافه کردن یا حذف محتوا باشد.
مثلاً محتوای فایل audience.txt
به این صورت است:
1 WHO THIS course is 2 ============================= 3 This course is for anyone who wants to learn Git.
شما میتوانید تغییرات زیر را اعمال کنید:
بعد از انجام ویرایشها، باید تغییرات را استیج کرده و کامیت کنید:
git add audience.txt git commit -m "Fix the signup Bug"
برای اطمینان از ثبت تغییرات، میتوانید تاریخچه کامیتها را با دستور زیر مشاهده کنید:
git log --oneline
این دستور لیستی از کامیتهای انجام شده را به شما نمایش میدهد.
بعد از اتمام کار، میتوانید به Branch اصلی (master
) بازگردید:
git switch master
اگر بخواهید تغییرات در فایل audience.txt
را بررسی کنید، خواهید دید که این تغییرات هنوز در شاخه اصلی اعمال نشدهاند. سپس برای حذف Branch bugfix
که دیگر به آن نیازی ندارید، میتوانید از دستور زیر استفاده کنید:
git branch -d bugfix
در صورتی که Branch به طور کامل ادغام نشده باشد و بخواهید آن را حذف کنید، از دستور زیر استفاده کنید:
git branch -D bugfix
از اونجایی ما به این Branch نیاز داریم فعلا اونو حذف نمیکنیم.
در، مقایسه Branchها به شما امکان مشاهده تغییرات قبل از ادغام را میدهد. این روش به شما کمک میکند تا ادغامهای مطمئنتری انجام دهید.
گام 1: مشاهده کامیتها بین Branchها
برای مشاهده کامیتها بین دو Branch، از دستور زیر استفاده کنید:
git log master....bugfix-sign
گام 2: مشاهده تغییرات در فایلها
برای دیدن تغییرات فایلها:
git diff master....bugfix-sign
گام 3: مشاهده فایلهای تغییر یافته
برای نمایش فایلهای تغییر یافته:
git diff --name-only ..bugfix-sign
گاهی ممکن است تغییراتی در Branch فعلی خود داشته باشید که کامل نشدهاند و نیاز به جابجایی به Branch دیگری دارید. در این موارد، به جای کامیت کردن تغییرات نیمهکاره، میتوانید از ویژگی Stashing برای ذخیره موقت آنها استفاده کنید.
الان ما توی master تغییراتی داشتیم و بدون اینکه کامیت کنیم تغییرات رو، و میخوام برم به یه برنچ دیگه با خظا روبرو میشیم میگه یا تغییرات رو باید کامیت کنی یا stash کنی.
برای ذخیره تغییرات فعلی:
git stash push -m "توضیح تغییرات"
اگر فایلهایی دارید که هنوز به گیت اضافه نشدهاند (فایلهای Untracked)، میتوانید از گزینه -a
برای ذخیره تمام تغییرات استفاده کنید:
git stash push -a -m "ذخیره تمامی تغییرات"
خب برای نشون دادن سناریو من اومدم تغییرات زیر رو اعمال کردم، یه فایلی که وجود داره رو تغییر دادم و یه فایل جدید ساختم.
الان بریم دستور رو اجرا کنیم و تغییرات رو ببینیم
برای مشاهده فهرست تغییرات ذخیرهشده:
git stash list
وقتی آماده بازگرداندن تغییرات ذخیرهشده هستید:
git stash apply stash@{0}
پس از اعمال تغییرات، بهتر است آنها را از لیست ذخیرههای موقت پاک کنید تا لیست شلوغ نشود:
git stash drop stash@{0}
اگر میخواهید همه ذخیرهها را پاک کنید:
git stash clear
ادر گیت، ادغام Branchها فرآیندی است که طی آن تغییرات یک Branch به Branch دیگری منتقل میشود. دو نوع اصلی ادغام وجود دارد:
مثال: تصور کنید روی یک ویژگی جدید کار میکنید. یک شاخه feature/login
ایجاد کردهاید و تمام تغییرات در آن شاخه هستند. در این مدت، شاخه master
تغییر نکرده است. پس هنگام ادغام، نیازی به ادغام سهطرفه نیست و گیت فقط شاخه master
را به آخرین وضعیت feature/login
هدایت میکند.
مثال: فرض کنید شما روی یک شاخه feature/change-password
کار میکنید و همزمان تغییرات جدیدی در شاخه master
ایجاد میشود. هر دو شاخه تغییرات متفاوتی دارند. در این حالت، گیت با استفاده از ادغام سهطرفه تغییرات هر دو شاخه را مقایسه میکند و یک کامیت جدید برای ترکیب آنها ایجاد میکند.
زمانی که تغییرات بین Branchها تداخلی ندارند، Git به طور خودکار از ادغام سریع (Fast-forward) استفاده میکند. این نوع ادغام فقط اشارهگر Branch را به آخرین کامیت منتقل میکند.
git merge bugfix
خروجی یک ادغام موفق:
در مواقعی که تغییراتی در هر دو Branch اعمال شده باشد، Git از ادغام ۳ طرفه استفاده میکند. در این روش، یک کامیت جدید ایجاد میشود که تاریخچه هر دو Branch را ترکیب میکند.
خب توی قدم اول میایم به سوئیچ no-ff-- این سناریو رو انجام میدیم و میبینیم که یه commit جدید ایجاد میشه
# Create a new branch and make changes git switch -C bug/login vim toc.txt git add . git commit -m "update toc.txt" # Switch back to master and perform a 3-way merge git switch master git merge --no-ff bug/login
در انتها میبینیم که یه commit اضافه شده به لیست commit ها حتی با وجود اینکه هیچ تغیییری توی master نداشتیم
بهطور پیشفرض، Git در صورت امکان از ادغام سریع استفاده میکند. اما میتوانید این رفتار را غیرفعال کنید تا همیشه یک کامیت ادغام جدید ایجاد شود و تاریخچه Branch حفظ شود.
git config ff no
git config --global ff no
با این تنظیمات، حتی اگر ادغام سریع ممکن باشد، Git همچنان یک کامیت ادغام جدید ایجاد میکند.
خب بریم یه مثال و سناریو داشته باشیم برای این مورد که هم master تغییراتی پیدا کرده و هم توی اون branch که کار میکردیم یه سری تغییرات دادیم
# Create a new branch and make changes git switch -C feature/change-password echo hello > change-password.txt git add . git commit -am "XX" # Switch back to master and make conflicting changes git switch master vim objective.txt git commit -am "XX" # Perform a three-way merge git merge feature/change-password
اگر تداخلی وجود داشته باشد، Git شما را مطلع میکند و باید به صورت دستی تداخلها را حل کرده و سپس ادغام را کامل کنید.
با دستور های زیر میتوینیم لیستشون رو ببینیم
# View branches that are merged git branch --merged # View branches that are not merged git branch --no-merged
به عنوان مثال عکس زیر لیست Branch هایی هست که Merge شدن
Merge Conflict زمانی رخ میدهد که دو Branch مختلف تغییرات متضادی در یک فایل داشته باشند و گیت نتواند به صورت خودکار این تغییرات را ادغام کند. این حالت بیشتر زمانی پیش میآید که چندین نفر به صورت همزمان روی یک پروژه کار میکنند یا شاخهها برای مدت طولانی بدون ادغام باقی میمانند. تعارضها معمولاً در خطوطی از فایل که هر دو شاخه تغییر دادهاند ظاهر میشوند، مثل وقتی که دو توسعهدهنده هر دو در یک بخش از کد تغییرات اعمال کرده باشند.
برای رفع confilict، نیاز است که توسعهدهنده فایل متعارض را به صورت دستی اصلاح کرده و سپس تغییرات را استیج و کامیت کند تا ادغام کامل شود.
خب بریم سناریو رو انجام بدیم تا کامل متوجه بشین
# Create a conflict scenario git switch -C bug/changepass vim audinece.txt git add . git commit -m "X" # Switch back to master and make conflicting changes git switch master vim change.txt git add . git commit -m "X" # Attempt to merge with conflicts git add . git commit -m "X"
خب همونطور که میبینیم خطایی داریم و میگه که توی audience.txt ما confilict داریم و باید به صورت دستی فایل رو باز کنیم و تغییرات رو اعمال کنیم.
با همچین فایلی روبرو میشیم و باید هر قسمت که confilict داریم رو بررسی و اون قسمت هایی که نیاز نداریم پاک کنیم و بعد از اون commit رو انجام میدیم
در گیت، اگر در حین ادغام متوجه شوید که نمیخواهید آن را ادامه دهید (مثلاً به دلیل بروز تعارضات پیچیده)، میتوانید از دستور git merge --abort
استفاده کنید تا ادغام را متوقف کرده و به حالت قبلی قبل از شروع ادغام برگردید. این دستور تمام تغییرات انجام شده در حین ادغام را بازنشانی میکند و پروژه شما را به وضعیتی که قبل از شروع عملیات ادغام بود، بازمیگرداند. این روش به خصوص زمانی مفید است که بخواهید به طور کامل از ادغام صرفنظر کنید.
توی عکس زیر نشون دادم که فایل رو merge کردیم دیدیم اون چیزی نیست که نیاز داریم دوباره برگشتم به قبل از merge کردن تا فایل به فایل قبلی برگرده
در گیت، زمانی که یک merge اشتباه انجام دادهاید و میخواهید آن را اصلاح کنید، دو راهکار اصلی وجود دارد:
git reset --hard HEAD~1
این دستور مخزن، استیج و دایرکتوری کاری را به حالت کامیت قبلی بازمیگرداند.
git revert HEAD~1
git revert -m1 HEAD~1
این دستور یک کامیت جدید ایجاد میکند که تغییرات ادغام اشتباه را معکوس میکند، بدون حذف تاریخچه.
در این بخش میخواهیم ادغام چند کامیت به یک کامیت را توضیح دهیم. وقتی چندین کامیت پشت سر هم دارید و میخواهید آنها را به یک کامیت واحد تبدیل کنید، میتوانید از قابلیت Squash Merge در گیت استفاده کنید. این روش به شما کمک میکند تا تاریخچه پروژه خود را تمیزتر نگه دارید و تغییرات پراکنده و غیرمرتبط را در قالب یک کامیت یکپارچه کنید.
مراحل انجام Squash Merge:
git switch -C photo echo bugfix >> audience.txt git commit -am "X" echo bugfix >> toc.txt git commit -am "X"
در این مثال، دو کامیت مختلف انجام دادیم که هر دو مرتبط با رفع مشکل (bugfix) هستند.
git merge --squash
کامیتها را به صورت یکپارچه ادغام کنید:git switch master git merge --squash photo git status -s git commit -m "fix the bug on the photo branch"
میتونیم ببینیم که توی commit ها توی master نیومدن
نکته مهم:
می که از دستور git merge --squash
استفاده میکنید، گیت فقط تغییرات branch مورد نظر رو ادغام میکند اما خود Branch ادغام نمیشود. به همین دلیل بسیار مهم است که پس از انجام این عملیات، شاخهای که squash شده را حذف کنید تا در آینده سردرگمی به وجود نیاید.
git branch -d photo
نتیجه:
در نهایت، با این روش میتوانید چندین کامیت را به یک کامیت تبدیل کنید و تاریخچه پروژه خود را ساده و تمیز نگه دارید. Squash Merge به ویژه در زمان رفع باگها یا اضافه کردن ویژگیهای کوچک به پروژه بسیار کاربردی است.
این توضیحات رو میتونی در مقالهات استفاده کنی و هر جا که لازم بود اسکرینشاتهای مربوط به مراحل رو اضافه کنی.
در این بخش میخواهیم درباره Rebase صحبت کنیم. Rebase یکی از مفاهیم مهم در گیت است که به شما اجازه میدهد تغییرات یک شاخه را بر روی شاخهای دیگر منتقل کنید، به خصوص زمانی که میخواهید شاخه مورد نظر خود را با آخرین تغییرات شاخه دیگر بهروزرسانی کنید. این کار باعث میشود تا تاریخچه پروژه تمیزتر و خطیتر باشد.
مراحل انجام Rebase:
git switch -C shopping echo hello > cart.txt git add . git commit -m "X"
در این مثال، ما یک فایل به نام cart.txt
ایجاد کردیم و تغییرات خود را کامیت کردیم.
حالا به شاخه اصلی (master) برگردید و در آن نیز تغییراتی اعمال کنید:
git switch master echo hello >> toc.txt git commit -m "X"
حالا وقت آن است که شاخه shopping
را به آخرین تغییرات شاخه master
متصل کنیم. برای این کار از دستور git rebase
استفاده میکنیم:
git switch shopping git rebase master git switch master git merge shopping
این دستور شاخه shopping
را بر اساس آخرین کامیتهای موجود در شاخه master
بهروزرسانی میکند. به عبارتی دیگر، تاریخچه shopping
بهگونهای تغییر میکند که انگار تمام تغییرات آن بعد از آخرین کامیت master
انجام شدهاند.
master
ادغام کنید:git switch master git merge shopping
نتیجه:
عملیات Rebase یک روش بسیار قدرتمند برای همگامسازی تغییرات شاخهها با یکدیگر است. با استفاده از Rebase، تاریخچه پروژه شما تمیزتر و خطیتر باقی میماند، و این کار باعث میشود که مدیریت تغییرات و کامیتها در پروژههای بزرگ و پیچیده راحتتر باشد.
وقتی شما عملیات Rebase انجام میدهید و تغییرات شاخهها با هم تضاد دارند (Conflict)، گیت شما را مطلع میکند تا آنها را حل کنید. در این بخش یاد میگیریم که چطور با این نوع تضادها مواجه شویم و آنها را مدیریت کنیم.
echo ocean > toc.txt git commit -am "Update toc.txt" git switch shopping echo mountain > toc.txt git commit -am "Update toc.txt"
در اینجا تغییرات مختلفی در فایل toc.txt
در شاخههای مختلف انجام شده که باعث ایجاد تضاد در هنگام انجام Rebase خواهد شد.
shopping
انجام میدهیم تا با تغییرات master
همگام شود:git rebase master
در این مرحله، گیت متوجه تضاد بین تغییرات فایل toc.txt
در شاخههای مختلف میشود و به شما اخطار میدهد تا این مشکل را حل کنید.
زمانی که با Conflict مواجه میشوید، گیت گزینههای مختلفی برای مدیریت وضعیت در اختیار شما قرار میدهد:
git add toc.txt git rebase --continue
-skip
استفاده کنید:git rebase --skip
-abort
استفاده کنید:git rebase --abort
وقتی با تضادها در عملیات Rebase مواجه شدید، گزینههای مختلفی برای حل یا مدیریت آنها وجود دارد. میتوانید تضادها را به صورت دستی حل کنید، از کامیتهای مشکلدار عبور کنید یا در صورت نیاز عملیات Rebase را لغو کنید. مدیریت صحیح تضادها یکی از کلیدیترین بخشهای کار با گیت است و به شما کمک میکند تا پروژههای پیچیدهتر را بهتر اداره کنید.
در این بخش، میخواهیم درباره Cherry Picking صحبت کنیم. Cherry Picking در گیت به شما اجازه میدهد که یک یا چند کامیت خاص از یک شاخه را به شاخه دیگری اعمال کنید، بدون اینکه نیاز باشد تمام تغییرات آن شاخه را ادغام (merge) کنید. این روش زمانی کاربرد دارد که شما میخواهید تنها تغییرات خاصی را از یک شاخه به شاخه خود بیاورید.
git cherry-pick
استفاده کنید:git cherry-pick <COMMIT ID>
با این دستور، تغییرات مربوط به آن کامیت خاص به شاخه فعلی شما اعمال میشود.
خب من ۳ تا کامیت زدم و برگردیم به مستر و فقط یه دونه از commit ها رو بیاریم merge کنیم.
با دستور زیر میتونیم کل commit ها رو ببینیم
git log --oneline --all
من بع عنوان مثال یکی از commit ها رو میارم توی master
پس از اعمال کامیت، میتوانید وضعیت پروژه خود را بررسی کرده و تغییرات را در صورت نیاز به صورت نهایی کامیت کنید، توی عکس بالا ما confilict داریم و با رفع اون میتونیم کامیت جدید رو انجام بدیم.
git status -s git commit -m "X"
Cherry Picking زمانی مفید است که شما میخواهید فقط یک تغییر خاص را به شاخه خود بیاورید، بدون اینکه تمام تاریخچه یا تغییرات شاخه مبدأ را ادغام کنید. این ویژگی به خصوص در پروژههای بزرگ و زمانی که تغییرات حساس یا موقتی هستند، بسیار کاربردی است.
. این روش زمانی کاربرد دارد که شما فقط میخواهید تغییرات یک فایل مشخص را از یک شاخه دیگر به شاخه فعلی خود اعمال کنید، بدون اینکه کل شاخه را ادغام کنید.
git switch -C sendEmail echo river > toc.txt git commit -am "update toc.txt"
در این مرحله، ما یک تغییر در فایل toc.txt
در شاخه sendEmail
ایجاد کردیم و آن را کامیت کردیم.
toc.txt
را از شاخه sendEmail
به شاخه اصلی بیاوریم، بدون اینکه نیاز باشد کل شاخه sendEmail
را ادغام کنیم. برای این کار از دستور git restore
استفاده میکنیم:git switch master git restore --source=sendEmail -- toc.txt
این دستور فایل toc.txt
را از شاخه sendEmail
بازیابی کرده و تغییرات آن را در شاخه master
اعمال میکند.
git status -s git add . git commit -m "X"