Fast-Forward Merge কী?

আগের উদাহরণগুলোতে দুই branch দুই দিকে এগিয়েছিল। কিন্তু ধরুন পরিস্থিতি এমন:

  D---E---F     main
           \
            A---B---C   feature

আপনি feature branch বানানোর পর main-এ নতুন কোনো commit আসেনি। feature-এর history-তে main-এর সব commit ইতিমধ্যেই আছে — main হলো feature-এর সরাসরি পূর্বপুরুষ (ancestor)।

এখন git merge feature করলে Git দেখে: "মার্জ করার তো কিছুই নেই, দুই লাইনের মধ্যে কোনো divergence-ই হয়নি।" তাই কোনো merge commit না বানিয়ে Git শুধু main-এর pointer-টা সামনে সরিয়ে C-তে নিয়ে যায়:

  D---E---F---A---B---C   main, feature

এটাই fast-forward। প্রথম আলোচনার কথা মনে করুন — branch যেহেতু শুধুই একটা pointer, তাই এখানে "merge" মানে আক্ষরিক অর্থে একটা ফাইলে নতুন hash লেখা। কোনো নতুন commit তৈরি হয় না, কোনো conflict সম্ভবই না। এজন্যই নাম fast-forward।

লক্ষ্য করুন: rebase করার পর merge করলে সবসময় fast-forward হয় — কারণ rebase-ই তো feature-কে main-এর মাথায় বসিয়ে দেয়, ফলে linear অবস্থা তৈরি হয়ে যায়।

সমস্যাটা কোথায়?

Fast-forward-এর পর history দেখে বোঝার উপায় নেই যে A, B, C কখনো একটা আলাদা feature branch ছিল। সব commit main-এর সরল লাইনে মিশে গেছে। তিনটা commit মিলে যে একটা logical unit — একটা feature — ছিল, সেই তথ্যটা হারিয়ে যায়।

--no-ff কেন ইচ্ছাকৃতভাবে ব্যবহার করবেন

git merge --no-ff feature

এটা Git-কে বলে: "fast-forward সম্ভব হলেও কোরো না, জোর করে একটা merge commit বানাও।"

  D---E---F---------M   main
           \       /
            A---B---C   feature

এখন history-তে "bump"-টা রয়ে গেল। কেন এটা চাইবেন:

১. Feature-এর সীমানা দৃশ্যমান থাকে। git log --graph-এ পরিষ্কার দেখা যায় কোন commit-গুলো কোন feature-এর অংশ। ছয় মাস পরে "এই ফিচারটা কী কী commit নিয়ে এসেছিল?" প্রশ্নের উত্তর merge commit-টাই দিয়ে দেয়।

২. পুরো feature এক কমান্ডে revert করা যায়। এটাই সবচেয়ে বড় ব্যবহারিক কারণ। Feature-টা production-এ সমস্যা করলে:

git revert -m 1 <merge-commit-hash>

এক ধাক্কায় পুরো feature undo। Fast-forward হয়ে থাকলে A, B, C আলাদা আলাদা revert করতে হতো, আর মাঝে অন্য কাজ ঢুকে গেলে সেটা আরো জটিল।

৩. Merge commit-টা metadata-র জায়গা। PR নম্বর, reviewer, ticket ID — সব ওখানে থাকে। GitHub-এর "Create a merge commit" অপশন আসলে --no-ff-ই করে, এজন্যই merge commit-গুলোতে "Merge pull request #123..." লেখা দেখেন।

বিখ্যাত git-flow মডেল এই কারণেই সব feature merge-এ --no-ff বাধ্যতামূলক করেছিল।

উল্টো দিক: fast-forward-ই যখন কাম্য

সবসময় --no-ff ভালো — তা না। যেখানে fast-forward-ই চাইবেন:

  • git pull-এ: origin/main-এ নতুন commit এসেছে, আপনার লোকালে কিছু নেই — এখানে merge commit বানানো অর্থহীন আবর্জনা। বরং অনেকে git config pull.ff only সেট করেন, যাতে fast-forward সম্ভব না হলে pull ব্যর্থ হয় এবং আপনি সচেতনভাবে সিদ্ধান্ত নিতে পারেন।
  • Squash-merge workflow-তে: feature পুরোটা এক commit হয়ে main-এ ঢুকছে — তখন branch-boundary রাখার প্রশ্নই নেই, ওই এক commit-ই পুরো feature।

সারমর্ম

Fast-forward --no-ff
নতুন commit হয় না, শুধু pointer সরে merge commit তৈরি হয়
History সরলরেখা, branch-এর চিহ্ন নেই branch-এর কাঠামো সংরক্ষিত
Feature revert commit ধরে ধরে এক কমান্ডে
উপযুক্ত pull, sync, ছোটখাটো আপডেট feature/release merge

Interview-তে এক লাইনে বলতে চাইলে: "Fast-forward হলো merge-এর নামে শুধু pointer সরানো; --no-ff দিয়ে আমরা ইচ্ছাকৃতভাবে merge commit রাখি যাতে feature-এর সীমানা history-তে টিকে থাকে এবং প্রয়োজনে পুরো feature-টা atomically revert করা যায়।"

Share