Vivasoft-logo

৫.২ ডিস্ট্রিবিউটেড গিট – একটি প্রজেক্টে কন্ট্রিবিউট করা

প্রজেক্টে কন্ট্রিবিউটশন

একটি প্রজেক্ট এ কীভাবে কন্ট্রিবিউট করতে হয় তা বর্ণনা করার প্রধান অসুবিধা হল, এটি কীভাবে করা যায় তার উপর অসংখ্য ভেরিয়েশন রয়েছে। গিট খুবই ফ্লেক্সিবল। এর মাধ্যমে মানুষ অনেক উপায়ে একসাথে কাজ করতে পারে। তাই আপনার কীভাবে কন্ট্রিবিউট করা উচিত তা বর্ণনা করা কঠিন। সকল প্রজেক্ট ই ভিন্ন ভিন্ন। প্রজেক্টে কুন্ট্রিবিউট করার জন্য মূল কিছু ভেরিয়েবল হল- একটিভ কন্ট্রিবিউটর কাউন্ট, চুজেন ওয়ার্কফ্লো, আপনার কমিট অ্যাক্সেস এবং এক্সটারনাল কন্ট্রিবিউশন মেথড।

প্রথম ভেরিয়েবলটি হল একটিভ কন্ট্রিবিউটর কাউন্টঃ কতজন ব্যবহারকারী সক্রিয়ভাবে এই প্রজেক্ট এ কোড কন্ট্রিবিউট করছেন, এবং কতবার? অনেক ক্ষেত্রে, আপনার কাছে দিনে কয়েকটি কমিট সহ দুই বা তিনজন ডেভেলপার থাকবে, অথবা কিছুটা সুপ্ত প্রজেক্ট এর জন্য জন্য সম্ভবত কিছু টা কম থাকতে পারে। বৃহত্তর কোম্পানি বা প্রজেক্ট এর জন্য, ডেভেলপারের সংখ্যা হাজার হাজার হতে পারে, প্রতিদিন শত শত বা হাজার হাজার কমিট আসে। এটি গুরুত্বপূর্ণ কারণ, আরও বেশি ডেভেলপারের সাথে, আপনার কোড পরিষ্কারভাবে এপ্লাই বা সহজেই মার্জ করা যায় কিনা তা নিশ্চিত করতে আপনি আরও সমস্যার সম্মুখীন হন। আপনার সাবমিট করা পরিবর্তনগুলি গুরুতরভাবে ভেঙে যেতে পারে যা আপনি কাজ করার সময় মার্জ হয়েছিল বা যখন আপনার পরিবর্তনগুলি ওয়েটিং এ বা এপ্রুভ হওয়ার অপেক্ষায় ছিল। কিভাবে আপনি আপনার কোড ধারাবাহিকভাবে আপ টু ডেট এবং আপনার কমিটগুলো বৈধ রাখতে পারেন?

পরবর্তী ভেরিয়েবলটি হল চুজেন ওয়ার্কফ্লোঃ এটি কি সেন্ট্রালাইজড রয়েছে? প্রতিটি ডেভেলপারের মূল কোডলাইনে সমানভাবে রাইট অ্যাক্সেস রয়েছে কি? প্রজেক্ট এর কি মেইন্টেইনার বা ইন্টিগ্রেশন ম্যানেজার রয়েছে, যিনি সবগুলো প্যাচ চেক করবেন? প্রত্যেকটি প্যাচ কি পিয়ার রিভিউ এবং এপ্রুভ হয়েছে? আপনি কি এই প্রক্রিয়ার সাথে জড়িত? এখানে কি লেফটেন্যান্ট সিস্টেম আছে এবং অপনার কি প্রথমে তাদের কাছে কাজ জমা দিতে হবে?

পরবর্তী ভেরিয়েবলটি হল কমিট অ্যাক্সেসঃ একটি প্রজেক্ট এ কন্ট্রিবিউট করার জন্য প্রয়োজনীয় ওয়ার্কফ্লো অনেকটাই আলাদা হয় যদি আপনার প্রজেক্ট এ রাইট এক্সেস থাকে। যদি আপনার রাইট অ্যাক্সেস ই না থাকে, তাহলে প্রজেক্ট কীভাবে আপনার কন্ট্রিবিউটেড কাজগুলো এক্সেপ্ট করবে? এটারও কি কোনো পলিসি আছে? আপনি এট এ টাইম কত গুলো কন্ট্রিবিউট করেছেন? কত ঘন ঘন আপনি কন্ট্রিবিউট করেন?

উপরের এই প্রশ্নগুলি ই বলে দেয় আপনি কিভাবে একটি প্রজেক্ট এ কার্যকরভাবে কন্ট্রিবিউট করতে পারেন এবং কোন ওয়ার্কফ্লোগুলি আপনার জন্য উপযুক্ত। আমরা এইগুলির প্রতিটি দিক একটি সিরিজ হিসেবে কভার করব। সহজ থেকে ধীরে ধীরে জটিল উদাহরণ দেখব। এই উদাহরণগুলি থেকে আপনি প্রয়োজনীয় ওয়ার্কফ্লো তৈরি করতে সক্ষম হবেন।

কমিট গাইডলাইন

আমরা নির্দিষ্ট উদাহরণ শুরু করার আগে, এখানে কমিট সম্পর্কে একটি কুইক নোট রয়েছে। কমিট তৈরি করার জন্য একটি ভাল নির্দেশিকা থাকা এবং এতে লেগে থাকা গিট-এর সাথে কাজ করা এবং অন্যদের সাথে সহযোগিতা করা যা সবকিছু সহজ করে তোলে। গিট প্রজেক্টটি এমন একটি ডকুমেন্ট প্রদান করে যা প্যাচ সাবমিট করার জন্য এবং কমিট তৈরি করার জন্য বেশ কয়েকটি ভাল টিপস দেয়। আপনি গিট সোর্স কোড এ এটি পড়ে দেখতে পারেন। এটি Documentation/SubmittingPatches ফাইলে রয়েছে। প্রথমত, আপনার সাবমিশনগুলোতে কোনো “হোয়াইট স্পেস ত্রুটি (whitespace error)” থাকা উচিত নয়। গিট এটি পরীক্ষা করার একটি সহজ উপায় প্রদান করে — আপনি কমিট করার আগে, git diff –check এই কমান্ড টি রান করুন, যা সম্ভাব্য হোয়াইটস্পেস ত্রুটি সনাক্ত করে এবং সেগুলি আপনার জন্য তালিকাভুক্ত করে।
Figure 56. git diff --check এর আউটপুট
আপনি যদি কমিট দেওয়ার আগে এই কমান্ডটি চালান তবে আপনি বলতে পারেন যে আপনি হোয়াইটস্পেস সমস্যাগুলি করতে চলেছেন যা অন্য ডেভেলপারদের বিরক্ত করতে পারে।

এরপর, প্রতিটি কমিটকে যৌক্তিকভাবে পৃথক একটি “পরিবর্তন সেট” করার চেষ্টা করুন। আপনি যদি পারেন, আপনার পরিবর্তনগুলি মিনিংফুল করার চেষ্টা করুন — পাঁচটি ভিন্ন বিষয়ে পুরো সপ্তাহজুড়ে কোড করবেন না এবং তারপরে সোমবারে একটি বিশাল কমিট হিসাবে সেগুলি জমা দেওয়ার প্রয়োজন নেই। এমনকি যদি আপনি সপ্তাহজুড়ে কমিট না করে থাকেন, তবে স্টেজিং এরিয়া ব্যাবহার করে প্রতি কমিট এ একটি প্রয়োজনীয় মেসেজ সহ প্রতি ইস্যুতে কমপক্ষে একটি কমিট করুন। যদি কিছু পরিবর্তন একই ফাইলে হয়, তাহলে git add –patch ব্যবহার করার চেষ্টা করুন যাতে করে আংশিকভাবে ফাইলগুলো স্টেজ এ রাখা যায়। (আরও বিস্তারিত এই লিংকে দেয়া আছে Interactive Staging)। যতক্ষন না আপনি কিছু চেঞ্জেস এড করছেন ততক্ষন পর্যন্ত প্রতিটি ব্রাঞ্চ এর অগ্রভাগে বা রুট এ প্রজেক্ট এর স্ন্যাপশট সম্পূর্ণ অভিন্ন, যদিও আপনি একটি বা পাচটি কমিট করেছেন। সুতরাং আপনার সহকর্মী ডেভেলপারদের যখন আপনার চেঞ্জেস বা পরিবর্তনগুলি রিভিউ করতে হবে তখন তাদের জন্য প্রতিটি চেঞ্জেস এবং কমিট সহজ করার চেষ্টা করুন।

এই পদ্ধতিটি আপনার যদি পরে প্রয়োজন হয় তবে চেঞ্জসেটগুলোর যেকোনো একটিকে পুল আউট করা বা রিভার্ট করা সহজ হয়ে যায়। Rewriting History এখানেহিস্টোরি পুনরায় রি রাইট এবং ইন্টারেক্টিভভাবে ফাইল স্টেজ করার জন্য বেশ কয়েকটি দরকারী গিট এর কৌশল রয়েছে — অন্য কাউকে কাজ দেয়ার আগে একটি পরিষ্কার এবং বোধগম্য হিস্টোরি তৈরি করতে এই টুলগুলি ব্যবহার করুন৷

সর্বশেষ যে জিনিসটি মনে রাখতে হবে তা হলো কমিট মেসেজ। মানসম্পন্ন কমিট মেসেজ তৈরি করার অভ্যাস করলে, গিট এর সাথে কোলাবোরেট করা এবং এর সাথে কাজ করা অনেক সহজ হয়ে যায়। একটি সাধারণ নিয়ম হিসাবে, আপনার মেসেজগুলি একটি একক লাইন দিয়ে শুরু হওয়া উচিত যা প্রায় ৫০ অক্ষরের বেশি নয় এবং যা সংক্ষিপ্তভাবে চেঞ্জসেটগুলিকে বর্ণনা করে, এরপরে একটি ফাকা লাইন থাকে ও কিছু বিশদ ব্যাখ্যা থাকে। গিট প্রজেক্টে এর জন্য আরও বিশদ ব্যাখ্যার প্রয়োজন যেখানে আপনার পূর্ববর্তী চেঞ্জগুলোর সাথে আপনার মোটিভেশন কি ছিলো, তা উল্লেখিত থাকবে —  এটি অনুসরণ করার জন্য একটি ভাল গাইডলাইন। অপনার কমিট মেসেজটি imperative sentence এ লিখুন যেমনঃ “Fix bug” কিন্তু “Fixed bug” অথবা “Fixes Bug” এভাবে লিখা উচিৎ নয়। এখানে একটি টেমপ্লেট রয়েছে যা আপনি অনুসরণ করতে পারেন, যা আমরা originally written by Tim Pope থেকে হালকাভাবে এডাপ্ট করে নিয়েছি।
				
					Capitalized, short (50 chars or less) summary

More detailed explanatory text, if necessary.  Wrap it to about 72
characters or so.  In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body.  The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase will confuse you if you run the
two together.

Write your commit message in the imperative: "Fix bug" and not "Fixed bug"
or "Fixes bug."  This convention matches up with commit messages generated
by commands like git merge and git revert.

Further paragraphs come after blank lines.

- Bullet points are okay, too

- Typically a hyphen or asterisk is used for the bullet, followed by a
  single space, with blank lines in between, but conventions vary here

- Use a hanging indent
				
			
যদি আপনার সমস্ত কমিট মেসেজ এই মডেলটি অনুসরণ করে, তাহলে আপনার এবং আপনি যাদের সাথে কোলাবোরেট করেন তাদের জন্য জিনিসগুলি অনেক সহজ হবে৷ গিট প্রজেক্ট এ ভাল ফর্ম্যাট করা কমিট মেসেজ রয়েছে। git log –no-merges এই কমান্ড টি রান করার চেষ্টা করুন তাহলে দেখবেন, একটি সুন্দর-ফরম্যাট করা প্রজেক্ট-কমিট হিস্টোরি দেখতে কেমন।
নোট
আমরা যেভাবে বলি সেভাবে কাজ করুন, আমরা যেভাবে কাজ করি সেভাবে নয়। (Do as we say, not as we do)

সংক্ষেপ করার জন্য, এই বই এর অনেক কমিট মেসেজ এর উদাহরণ সুন্দরভাবে ফরম্যাট করা সম্ভব হয়নি।এর পরিবর্তে, আমরা সহজভাবে -m option টি ইউজ করেছি git commit করার জন্য।

সংক্ষেপে আমরা বলি, do as we say, not as we do.

ব্যাক্তিগত ছোট টিম

আপনি যে সহজতম সেটআপের মুখোমুখি হতে পারেন তা হল এক বা দুইজন ডেভেলপারের সাথে একটি প্রাইভেট বা ব্যক্তিগত প্রজেক্ট। প্রাইভেট বা ব্যক্তিগত বলতে ক্লোজড প্রজেক্ট বুঝানো হয়েছে — যেটি আউটসাইড ওয়ার্ল্ড এ এক্সেস করা সম্ভব নয়। চাইলেই যে কেউ এই প্রজেক্ট এ এক্সেস করতে পারবে না। শুধুমাত্র আপনি এবং আপনার সহযোগী ডেভেলপারদের সকলের পুশ এক্সেস রয়েছে।

এই এনভাইরনমেন্টে, আপনি সাবভারশন বা অন্য সেন্ট্রালাইজড সিস্টেম ব্যবহার করার সময় আপনি যা যা করতে পারেন তার অনুরূপ একটি ওয়ার্কফ্লো অনুসরণ করতে পারেন। তাহলে আপনি একইভাবে অফলাইন কমিটিং এবং ব্যাপকভাবে সহজ ব্রাঞ্চিং এবং মার্জ করার মতো জিনিসগুলির সুবিধাগুলি পাবেন। প্রধান পার্থক্য হল যে মার্জগুলি কমিট এর সময়ে সার্ভারের পরিবর্তে ক্লায়েন্ট-সাইডে ঘটে। দেখা যাক দুইজন ডেভেলপার যখন একটি শেয়ার্ড রিপোজিটরির সাথে একসাথে কাজ করা শুরু করে তখন এটি কেমন হতে পারে। প্রথম ডেভেলপার, জন, রিপোজিটরি ক্লোন করে, একটি ফাইলে চেঞ্জ করে এবং লোকালি কমিট করে। প্রোটোকল মেসেজগুলিকে কিছুটা সংক্ষিপ্ত করতে এই উদাহরণগুলিতে … এর সাথে রিপ্লেস করা হয়েছে।
				
					# John's Machine
$ git clone john@githost:simplegit.git
Cloning into 'simplegit'...
...
$ cd simplegit/
$ vim lib/simplegit.rb
$ git commit -am 'Remove invalid default value'
[master 738ee87] Remove invalid default value
 1 files changed, 1 insertions(+), 1 deletions(-)
				
			
দ্বিতীয় ডেভেলপার, জেসিকা, একই কাজ করে —রিপোজিটরি ক্লোন করে এবং একটি ফাইলে চেঞ্জ করে।
				
					# Jessica's Machine
$ git clone jessica@githost:simplegit.git
Cloning into 'simplegit'...
...
$ cd simplegit/
$ vim TODO
$ git commit -am 'Add reset task'
[master fbff5bc] Add reset task
 1 files changed, 1 insertions(+), 0 deletions(-)
				
			
এখন, জেসিকা তার কাজকে সার্ভারে পুশ করে, যা ঠিক কাজ করেঃ
				
					# Jessica's Machine
$ git push origin master
...
To jessica@githost:simplegit.git
   1edee6b..fbff5bc  master -> master
				
			

উপরের আউটপুটের শেষ লাইনটি পুশ অপারেশন থেকে একটি দরকারী রিটার্ন মেসেজ দেখায়। বেসিক ফর্মেট টি হল <oldref>..<newref> fromref → toref, যেখানে oldref এর মানে হল old reference, newref মানে হলো new reference, fromref হল লোকাল রেফারেন্সের নাম যা পুশ করা হচ্ছে এবং toref হল রিমোট রেফারেন্সের নাম আপডেট করা হচ্ছে। আপনি নীচের আলোচনায় অনুরূপ আউটপুট দেখতে পাবেন। এগুলোর মিনিং সম্পর্কে প্রাথমিক ধারণা থাকা রিপোজিটরির বিভিন্ন অবস্থা বুঝতে সাহায্য করবে। আরও ডিটেইলস ডকুমেন্টেশন git-push এ রয়েছে। 

 

এই উদাহরণটি চালিয়ে, কিছুক্ষণ পরে, জন কিছু পরিবর্তন করে, সেগুলিকে তার লোকাল রিপোজিটরিতে কমিট করে এবং সেগুলিকে একই সার্ভারে পুশ দেওয়ার চেষ্টা করেঃ

				
					# John's Machine
$ git push origin master
To john@githost:simplegit.git
 ! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to 'john@githost:simplegit.git'
				
			
এই ক্ষেত্রে, জনের পুশ ব্যর্থ হয় কারণ জেসিকার তার চেঞ্জেসগুলো আগেই পুশ করেছে। সুতরাং আপনি সাবভারশনে অভ্যস্ত কিনা তা বোঝা বিশেষভাবে গুরুত্বপূর্ণ, কারণ আপনি লক্ষ্য করবেন যে দুই ডেভেলপারই একই ফাইল সম্পাদনা করেননি। যদিও সাবভার্সন স্বয়ংক্রিয়ভাবে সার্ভারে এই ধরনের মার্জ করে, যদি গিট দিয়ে বিভিন্ন ফাইল এডিট করা হয়, আপনাকে প্রথমে লোকালি কমিটগুলি মার্জ করতে হবে। অন্য কথায়, পুশ করার আগে জনকে প্রথমে জেসিকার আপস্ট্রিম এর চেঞ্জগুলি ফেচ করে আনতে হবে এবং সেগুলিকে তার লোকাল রিপোজিটরিতে মার্জ করতে হবে।

প্রথম ধাপ হিসেবে, জন জেসিকার কাজগুলো ফেচ করে নিয়ে আসে (এটি শুধুমাত্র জেসিকার আপস্ট্রিম এর কাজগুলো ফেচ করে নিয়ে আসে, এটি এখনও জনের কাজের সাথ মার্জ করেনি)ঃ
				
					$ git fetch origin
...
From john@githost:simplegit
 + 049d078...fbff5bc master     -> origin/master
				
			
এই মুহুর্তে, জনের লোকাল রিপোজিটরি এরকম দেখায়ঃ
Figure 57. John’s divergent history
এখন জন জেসিকার কাজকে মার্জ করতে পারেন যা তিনি তার নিজের লোকাল কাজে এনেছিলেন:
				
					$ git merge origin/master
Merge made by the 'recursive' strategy.
 TODO |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
				
			
যতক্ষণ না সেই লোকাল মার্জটি স্মুথ বা সাবলীলভাবে চলে, জনের আপডেট করা হিস্টোরি এখন এইরকম দেখাবে:
Figure 58. John’s repository after merging origin/master
এই মুহুর্তে, জন এই নতুন কোডটি পরীক্ষা করতে চাইতে পারেন যাতে নিশ্চিত হয় যে জেসিকার কোনো কাজই তার কোনোটিকে প্রভাবিত করে না এবং যতক্ষণ পর্যন্ত সবকিছু ঠিকঠাক মনে হচ্ছে, ততক্ষণ সে নতুন মার্জ করা কাজটিকে সার্ভারে পুশ করে দিতে পারে:
				
					$ git push origin master
...
To john@githost:simplegit.git
   fbff5bc..72bbc59  master -> master
				
			
শেষ পর্যন্ত, জন এর কমিট হিস্টোরি এই রকম দেখাবেঃ
Figure 59. John’s history after pushing to the origin server
ইতিমধ্যে, জেসিকা issue54 নামে একটি নতুন ব্রাঞ্চ তৈরি করেছে এবং সেই ব্রাঞ্চে তিনটি কমিট দিয়েছে৷ তিনি এখনও জনের পরিবর্তনগুলি পাননি, তাই তার কমিট হিস্টোরি এইরকম দেখাচ্ছেঃ
Figure 60. Jessica’s topic branch
হঠাৎ, জেসিকা জেনেছে যে জন সার্ভারে কিছু নতুন কাজ পুশ দিয়েছে এবং সে এটি দেখতে চায়, তাই সে সার্ভার থেকে সমস্ত নতুন কন্টেন্টগুলো ফেচ করে আনতে পারে যা তার কাছে এখনও নেইঃ
				
					# Jessica's Machine
$ git fetch origin
...
From jessica@githost:simplegit
   fbff5bc..72bbc59  master     -> origin/master
				
			
এর মধ্যে যে কাজটি জন নিজে পুশ করেছে তা পুল ডাউন করে। জেসিকার ইতিহাস এখন এই রকমদেখায়ঃ
Figure 61. Jessica’s history after fetching John’s changes
জেসিকা মনে করেন তার টপিকের ব্রাঞ্চ প্রস্তুত, কিন্তু সে জানতে চায় জন এর আনা কাজের কোন অংশ তাকে তার কাজে মার্জ করতে হবে যাতে সে পুশ দিতে পারে। তিনি তা খুঁজে বের করতে git log কমান্ডটি রান করেনঃ
				
					$ git log --no-merges issue54..origin/master
commit 738ee872852dfaa9d6634e0dea7a324040193016
Author: John Smith <jsmith@example.com>
Date:   Fri May 29 16:01:27 2009 -0700

   Remove invalid default value
				
			
issue54..origin/master হল একটি লগ ফিল্টার যা গিটকে শুধুমাত্র সেই কমিটগুলি প্রদর্শন করতে বলে যেগুলো পরবর্তী ব্রাঞ্চ এ আছে (এই ক্ষেত্রে origin/master) এবং যেগুলো প্রথম ব্রাঞ্চ এ নেই (এই ক্ষেত্রে issue54)। আমরা Commit Ranges-এ এই সিনট্যাক্সের উপর বিস্তারিতভাবে দেখব।

উপরের আউটপুট থেকে, আমরা দেখতে পাচ্ছি যে একটি সিঙ্গেল কমিট আছে যা জন তৈরি করেছে, কিন্তু জেসিকা তার লোকাল কাজে মার্জ করেনি। যদি সে origin/master কে মার্জ করে, তবে এটিই সিঙ্গেল কমিট যা তার লোকাল কাজকে মডিফাই করবে।

এখন, জেসিকা তার বিষয়ের কাজটি তার মাস্টার ব্রাঞ্চে মার্জ করতে পারে। জন এর কাজ (origin/master) তার মাস্টার ব্রাঞ্চে মার্জ করতে পারে এবং তারপর আবার সার্ভারে পুশ ব্যাক করতে পারে।

প্রথমে (তার issue54 ব্রাঞ্চ এর সমস্ত কাজ কমিট করে), জেসিকা এই সমস্ত কাজকে একীভূত করার প্রস্তুতির জন্য তার মাস্টার ব্রাঞ্চ এ ফিরে যানঃ
				
					$ git checkout master
Switched to branch 'master'
Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
				
			
জেসিকা প্রথমে origin/master অথবা issue54 মার্জ করতে পারে — দুটি ব্রাঞ্চ উভয়ে আপস্ট্রিম এ রয়েছে। তাই অর্ডার কোনো ব্যাপার না। শেষের স্ন্যাপশটটি আইডেন্টিকাল বা অভিন্ন হওয়া উচিত। সে যে অর্ডারই বেছে নেয় না কেন; শুধু হিস্টোরি ভিন্ন হবে। তিনি প্রথমে issue54 ব্রাঞ্চটি মার্জ করার জন্যবেছে নেনঃ
				
					$ git merge issue54
Updating fbff5bc..4af4298
Fast forward
 README           |    1 +
 lib/simplegit.rb |    6 +++++-
 2 files changed, 6 insertions(+), 1 deletions(-)
				
			
এখানে আমরা দেখবো যে, কোনো সমস্যা হয়না; যেহেতু এটি একটি সিম্পল ফাস্ট-ফরওয়ার্ডেড মার্জ ছিল। জেসিকা এখন জনের পূর্বে আনা কাজগুলিকে মার্জ করে লোকাল মার্জিং প্রক্রিয়াটি সম্পূর্ণ করেছে, যা origin/master ব্রাঞ্চ এ রয়েছে।
				
					$ git merge issue54
Updating fbff5bc..4af4298
Fast forward
 README           |    1 +
 lib/simplegit.rb |    6 +++++-
 2 files changed, 6 insertions(+), 1 deletions(-)
				
			

সবকিছু পরিষ্কারভাবে মার্জ হয়, এবং জেসিকার হিস্টোরি এখন এই রকম দেখাযঃ

Figure 62. Jessica’s history after merging John’s changes
এখন জেসিকার মাস্টার ব্রাঞ্চ থেকে origin/master-এ পৌঁছানো যায়, তাই তাকে সফলভাবে পুশ দিতে সক্ষম হওয়া উচিত (ধরে নেওয়া হচ্ছে জন এর মধ্যে আরও বেশি পরিবর্তন করেননি):
				
					
$ git push origin master
...
To jessica@githost:simplegit.git
   72bbc59..8059c15  master -> master
				
			

প্রতিটি ডেভেলপার কয়েকবার কমিট দিয়েছে এবং একে অপরের কাজ সফলভাবে মার্জ করেছে।

Figure 63. Jessica’s history after pushing all changes back to the server
এটি সবচেয়ে সহজ ওয়ার্কফ্লোগুলোর মধ্যে একটি। আপনি কিছু সময়ের জন্য (সাধারণত একটি ব্রাঞ্চ এ) কাজ করেন, এবং সেই কাজটি আপনার মাস্টার ব্রাঞ্চ এ মার্জ করুন, যখন এটি ইনটিগ্রেটেড হওয়ার জন্য প্রস্তুত হয়। আপনি যখন সেই কাজটি শেয়ার করতে চান, তখন আপনি আপনার master ব্রাঞ্চ কে origin/master থেকে ফেচ করে আনবেন এবং যদি এটি পরিবর্তিত হয় তাহলে মার্জ করবেন। পরিশেষে master ব্রাঞ্চ এ পুশ করবেন। জেনারেল সিকুয়েন্সটি সাধারণত এরকমঃ
Figure 63. Jessica’s history after pushing all changes back to the server
এটি সবচেয়ে সহজ ওয়ার্কফ্লোগুলোর মধ্যে একটি। আপনি কিছু সময়ের জন্য (সাধারণত একটি ব্রাঞ্চ এ) কাজ করেন, এবং সেই কাজটি আপনার মাস্টার ব্রাঞ্চ এ মার্জ করুন, যখন এটি ইনটিগ্রেটেড হওয়ার জন্য প্রস্তুত হয়। আপনি যখন সেই কাজটি শেয়ার করতে চান, তখন আপনি আপনার master ব্রাঞ্চ কে origin/master থেকে ফেচ করে আনবেন এবং যদি এটি পরিবর্তিত হয় তাহলে মার্জ করবেন। পরিশেষে master ব্রাঞ্চ এ পুশ করবেন। জেনারেল সিকুয়েন্সটি সাধারণত এরকমঃ
Figure 64. General sequence of events for a simple multiple-developer Git workflow

প্রাইভেট ম্যানেজড টিম (ব্যক্তিগত পরিচালিত দল)

এর পরবর্তী দৃশ্যে, আপনি একটি বৃহত্তর ব্যক্তিগত গ্রুপ এ কন্ট্রিবিউটরের ভূমিকাগুলো দেখবেন। আপনি এমন একটি পরিবেশে কীভাবে কাজ করবেন তা শিখবেন, যেখানে ছোট গ্রুপগুলো ফিচারগুলিতে কোলাবোরেট করে। এর পরে সেই গ্রুপ ভিত্তিক কন্ট্রিবিউশনগুলি অন্য পক্ষ দ্বারা ইন্টিগ্রেট হয়।

ধরা যাক জন এবং জেসিকা একটি ফিচার এ একসাথে কাজ করছেন, (চলুন এটাকে আমরা “featureA” নামে ডাকি)। অন্যদিকে জেসিকা এবং তৃতীয় একজন ডেভেলভার, জোসি, দ্বিতীয় একটি ফিচার (এটিকে featureB নামে ডাকি) এ কাজ করছেন। এই ক্ষেত্রে, কোম্পানিটি একটি ইন্টিগ্রেশন-ম্যানেজার ওয়ার্কফ্লো ব্যবহার করছে, যেখানে ইনডিভিজুয়াল গ্রুপের কাজ কিছু নির্দিষ্ট ইঞ্জিনিয়ারদের দ্বারা ইন্টিগ্রেট করা হচ্ছে এবং মেইন রিপো’র মাস্টার ব্রাঞ্চ কে কেবল উক্ত ইঞ্জিয়ারদের দারাই আপডেট করা যেতে পারে। এই পরিস্থিতিতে, সমস্ত কাজ টীম-ভিত্তিক ব্রাঞ্চে করা হয় এবং পরে ইন্টিগ্রেটরদের দ্বারা পুল(Pull) বা একত্রিত করা হয়।

চলুন আমরা জেসিকার কাজের ফাংশনটি ফলো করি,, যেহেতু তারা এখানে দুইটি ফিচারে কাজ করছে এবং দুটি ভিন্ন ডেভেলপারের সাথে প্যারালেল কোলাবোরেটিং করছে। ধারণা করা যাক, তিনি ইতোমধ্যেই তার রিপোজিটরিটি ক্লোন করেছেন, তিনি প্রথমে featureA তে কাজ করার সিদ্ধান্ত নিয়েছেন। তিনি ফিচারের জন্য একটি নতুন ব্রাঞ্চ তৈরি করেছেন এবং সেখানে কিছু কাজ করেছেন।
				
					# Jessica's Machine
$ git checkout -b featureA
Switched to a new branch 'featureA'
$ vim lib/simplegit.rb
$ git commit -am 'Add limit to log function'
[featureA 3300904] Add limit to log function
 1 files changed, 1 insertions(+), 1 deletions(-)
				
			
এখন পর্যন্ত, তিনি জনকে তার কাজটি শেয়ার করতে চান, তাই তিনি তার featureA ব্রাঞ্চের কমিট সার্ভারে পুশ করে। জেসিকার মাস্টার ব্রাঞ্চে পুশ এক্সেস নেই — শুধুমাত্র ইন্টিগ্রেটর রা পুশ করতে পারে — সুতরাং জন এর সাথে কোলাবোরেট করার জন্য তাকে অন্য একটি ব্রাঞ্চে পুশ করতে হবেঃ
				
					
$ git push -u origin featureA
...
To jessica@githost:simplegit.git
 * [new branch]      featureA -> featureA
				
			
জেসিকা এখন জন-কে ইমেল দিল এবং বলল তার কিছু কাজ featureA ব্রাঞ্চ এ পুশ করা হয়েছে, সে এখন এটি দেখতে পারে। জন এর ফিডব্যাক পাওয়ার মধ্যবর্তী সময়ে জেসিকা featureB তে কাজ শুরু করল জোসির সাথে। সে এখন একটি ফিচার ব্রাঞ্চ ক্রিয়েট করল এবং মাস্টার ব্রাঞ্চ কে বেইস মডেল হিসেবে রাখলঃ
				
					# Jessica's Machine
$ git fetch origin
$ git checkout -b featureB origin/master
Switched to a new branch 'featureB'
				
			
এখন জেসিকা featureB ব্রাঞ্চে কিছু কমিট করলঃ
				
					$ vim lib/simplegit.rb
$ git commit -am 'Make ls-tree function recursive'
[featureB e5b0fdc] Make ls-tree function recursive
 1 files changed, 1 insertions(+), 1 deletions(-)
$ vim lib/simplegit.rb
$ git commit -am 'Add ls-files'
[featureB 8512791] Add ls-files
 1 files changed, 5 insertions(+), 0 deletions(-)
				
			
জেসিকার রিপোজিটরি এখন এইরকম হবেঃ
Figure 65. Jessica’s initial commit history
সে তার কাজগুলো পুশ করার জন্য প্রস্তুত, কিন্তু জোসি থেকে একটি ইমেইল পেল যে জোসি “featureBee” নামক ব্রাঞ্চটিতে কিছু ফিচার চেঞ্জ করেছে এবং এটি সার্ভারে পুশ করা হয়েছে। জেসিকার এখন এই চেঞ্জগুলো মার্জ করতে হবে তার নিজের ব্রাঞ্চ এর সাথে। এরপর ই শুধুমাত্র সে সার্ভারে তার কাজগুলো পুশ করতে পারবে। এখন জেসিকা প্রথমে জোসির কাজগুলো ফেচ করে নিয়ে আসল এই কমান্ডটির মাধ্যমে “git fetch”:
				
					$ git fetch origin
...
From jessica@githost:simplegit
 * [new branch]      featureBee -> origin/featureBee
				
			
মনে করি জেসিকা এখনও তার “featureB” নামক ব্রাঞ্চটিতেই চেক আউট অবস্থায় রয়েছে, এখন সে তার কাজগুলোকে জোসির কাজগুলোর সাথে মার্জ করতে পারবে এই কমান্ডটির সাহায্যে “git merge”
				
					$ git merge origin/featureBee
Auto-merging lib/simplegit.rb
Merge made by the 'recursive' strategy.
 lib/simplegit.rb |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
				
			
এখন এই পয়েন্টে জেসিকা তার featureB এর কাজগুলো সার্ভারে মার্জ করতে ইচ্ছুক, কিন্তু সে শুধুমাত্র তার নিজের featureB ব্রাঞ্চটি পুশ করতে চাচ্ছে না। যেহেতু, জোসি আপস্ট্রিম এ আছে এবং featureBee ব্রাঞ্চ এ আছে। এখন জেসিকা featureBee ব্রাঞ্চ এ পুশ করতে চান এবং তাই করা উচিৎ এভাবেঃ
				
					$ git push -u origin featureB:featureBee
...
To jessica@githost:simplegit.git
   fba9af8..cd685d1  featureB -> featureBee
				
			
এটাকে refspec বলা হয়।  The Refspec এ বিস্তারিত দেখুন। এরপর -u flag টি খেয়াল করুন। এটি –set-upstream নামে পরিচিত যা ব্রাঞ্চগুলোকে পরবর্তীতে সহজভাবে কনফিগার করে।

হঠাত জেসিকা জন এর কাছ থেকে একটি ইমেইল পেল। জেসিকা কে বলা হল featureA ব্রাঞ্চ এ কিছু চেঞ্জ পুশ করা হয়েছে, যেখানে তারা কোলাবোরেট করছে। সে জেসিকাকে এটি দেখতে বলল। এরপর জেসিকা আবারও “git fetch” কমান্ডটি রান করল যাতে জনের সকল কন্টেন্ট সার্ভার থেকে চলে আসে।
				
					$ git fetch origin
...
From jessica@githost:simplegit
   3300904..aad881d  featureA   -> origin/featureA
				
			
জেসিকা নতুন ফেচ করা কাজগুলোর সাথে তুলনা করে, এখন জনের নতুন কাজগুলোর লগ দেখতে পারবে।
				
					$ git log featureA..origin/featureA
commit aad881d154acdaeb2b6b18ea0e827ed8a6d671e6
Author: John Smith <jsmith@example.com>
Date:   Fri May 29 19:57:33 2009 -0700

    Increase log output to 30 from 25

				
			
যদি জেসিকা চেঞ্জগুলো দেখে পছন্দ করে তাহলে সে তার featureA ব্রাঞ্চ এ এই কাজগুলো কে মার্জ করে নিতে পারবেঃ
				
					$ git checkout featureA
Switched to branch 'featureA'
$ git merge origin/featureA
Updating 3300904..aad881d
Fast forward
 lib/simplegit.rb |   10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
				
			
সবশেষে, সবকিছু মার্জ করার পর জেসিকা কিছু মাইনর চেঞ্জ করতে চাচ্ছে, সুতরাং তিনি এখন এই চেঞ্জগুলো করার জন্য সম্পূর্ণভাবে প্রস্তুত। তিনি এখন তার লোকাল featureA ব্রাঞ্চে কমিট করতে পারবেন এবং তার সর্বশেষ কাজের রেজাল্টগুলো সার্ভারে আবারও পুশ করতে পারবেন।
				
					$ git commit -am 'Add small tweak to merged content'
[featureA 774b3ed] Add small tweak to merged content
 1 files changed, 1 insertions(+), 1 deletions(-)
$ git push
...
To jessica@githost:simplegit.git
   3300904..774b3ed  featureA -> featureA
				
			
জেসিকার কমিট হিস্টোরি এখন এইরকম দেখাবেঃ
Figure 66. Jessica’s history after committing on a feature branch
একটা সময়ে জেসিকা এবং জন ইন্টিগ্রেটরদেরকে জানালো যে, featureA এবং featureB ব্রাঞ্চ দুইটি মেইন লাইনে ইন্টিগ্রেট করার জন্য প্রস্তুত। ইন্টেগ্রেটরগুলো এই ব্রাঞ্চগুলোকে মেইনলাইনে মার্জ করার পরে, ফেচ নিয়ে নতুন মার্জ কমিট ডাউন করবে, এতে হিস্টোরি এমন দেখা যাবে:
Figure 67. Jessica’s history after merging both her topic branches
এই এবিলিটির মাধ্যমে অনেক অনেক গ্রুপ গিট এ সুইচ করেছে, কারণ একাধিক টিম এখানে একই সাথে কাজ করতে পারছে এবং একই সাথে আলাদা আলাদা লাইনগুলো মার্জ করতে পারছে যদিও সেগুলো প্রসেস এর ফ্লো তে শেষে এসেছে। গিট এর সবচাইতে বড় উপকার হচ্ছে, সম্পূর্ণ টিম এর সাথে সরাসরি ইনভল্ব না থেকেও, ছোট ছোট সাবগ্রুপগুলো রিমোট ব্রাঞ্চ এর মাধ্যমে কোলাবোরেট করার এবিলিটি পাচ্ছে। এই ওয়ারকফ্লো এর সিকুয়েন্সটি এইরকম দেখাবেঃ
Figure 68. Basic sequence of this managed-team workflow

ফর্ক করা পাবলিক প্রোজেক্ট

পাবলিক প্রোজেক্ট এ কন্ট্রিবিউট করা একটু আলাদা। কারণ সরাসরি প্রোজেক্ট এর ব্রাঞ্চে আপনার আপডেট করার অনুমতি নেই। আপনাকে অন্য কোনো উপায়ে মেইন্টেইনারদের কাছে কাজ পাঠাতে হবে। প্রথম উদাহরণটি সহজভাবে ফর্কিং এর মাধ্যমে গিট হোস্ট এ কন্ট্রিবিউট করাকে সমর্থন করে। অনেক হোস্টিং সাইটগুলো এটি সাপোর্ট করে (যেমনঃ GitHub, BitBucket, repo.or.cz এবং আরও অনেক রয়েছে) এবং অনেক প্রোজেক্ট মেইন্টেইনাররা এই কন্ট্রিবিউশনের এই স্টাইলগুলো এক্সপেক্ট করে। পরবর্তী অনুচ্ছেদটি প্রোজেক্টগুলোর সাথে এমনভাবে ডিল করে যা ই-মেইলের মাধ্যমে কন্ট্রিবিউটেড প্যাচ গ্রহণ প্রেফার করে।

প্রথমত আপনি হয়তো মেইন রিপোজিটরি ক্লোন করতে পছন্দ করবেন। একটি প্যাচ বা প্যাচ সিরিজ এর জন্য একটি টপিক ব্রাঞ্চ তৈরি করুন, যেটি আপনি প্ল্যান করেছেন এবং সেখানে আপনার প্রেফারেবল কাজগুলো করুন। এই সিকুন্সটি সাধারণত এরকম হয়ঃ
				
					$ git clone <url>
$ cd project
$ git checkout -b featureA
  ... work ...
$ git commit
  ... work ...
$ git commit
				
			
নোট

মেইন্টেইনারদের জন্য প্যাচ ইজি করার ক্ষেত্রে, কমিটগুলোতে আপনি হয়ত আপনার কাজকে squash অথবা রিএরেঞ্জ করার জন্য  rebase -i ইউজ করতে চাচ্ছেন । রিবেইজিং এর জন্য এই Rewriting History তে দেখুন আরও ইনফরমেশন রয়েছে।

যখন আপনার ব্রাঞ্চ এর কাজগুলো শেষ এবং আপনি কাজগুলো মেইন্টেইনারদেরকে কন্ট্রিবিউট করার জন্য প্রস্তুত, তখন আপনি অরিজিনাল প্রোজেক্ট এর পেইজ এ যান এবং “Fork” বাটনে ক্লিক করুন এবং আপনার প্রোজেক্ট এর নিজস্ব writable fork তৈরি করুন। এরপর আপনাকে এই রিপোজিটরি url টি একটি নতুন রিমোট লোকাল রিপোজিটরি হিসেবে এড করতে হবে। এই উদাহরণটিতে চলুন এটিকে myFork নামে কল করিঃ
				
					$ git remote add myfork <url>
				
			
এরপর আপনার নতুন কাজগুলো এই রিপোজিটরিতে পুশ করতে হবে। মাস্টার ব্রাঞ্চে মার্জ এবং পুশ করার চাইতে, টপিক ব্রাঞ্চটি ফর্ক করা রিপোজিটরি তে পুশ করা সুবিধাজনক। কারণ যদি আপনার কাজটি এক্সেপ্ট না করা হয় তাহলে মাস্টার ব্রাঞ্চটি আপনাকে আবারও রিওয়াইন্ড বা পুনঃস্থাপন করার প্রয়োজন হবে না। (গিট এর cherry-pick অপারেশনটি আরও বিশদভাবে  Rebasing and Cherry-Picking Workflows এখানে আলোচনা করা হয়েছে)। যদি মেইন্টেইনাররা আপনার কাজগুলোকে merge, rebase বা cherry-pick করে, তবে আপনি এটি তাদের রিপোজিটরি থেকে পুল করার মাধ্যমে ফিরে পাবেন।

যে কোনো ইভেন্টে আপনার কাজগুলোকে এইভাবে পুশ করতে পারেনঃ
				
					git push -u myfork featureA
				
			
একবার আপনার কাজগুলো ফর্ক রিপোজিটরিতে পুশ হওয়ার পর, আপনাকে অরিজিনাল প্রোজেক্ট এর মেইন্টেইনারদের নোটিফাই করতে হবে যে, আপনার কাজ রয়েছে এবং আপনি এটি মার্জ করতে ইচ্ছুক। এটি  “Pull Request” মেকানিজম নামে বহুল পরিচিত। এটি আমরা  GitHub এ দেখে থাকব— অথবা আপনি “git request-pull” এই কমান্ডটি রান করতে পারেন এবং মেইন্টেইনারদেরকে যথাযথ আউটপুট দিয়ে একটি ইমেইল পাঠাতে পারেন।  

Git request-pull কমান্ডটি আপনার টোপিক ব্রাঞ্চটি যে ব্রাঞ্চে পুল করতে চান তার বেইজ ব্রাঞ্চ এবং যেখান থেকে আপনি পুল করতে চান তার গিট রিপোজিটরি url  নেয়, এবং সকল change summary প্রডিউস করে যেগুলো আপনি পুল করতে বলেছেন। যেমনঃ জেসিকা জনকে একটি পুল রিকুয়েস্ট দিতে চায়, এবং সে টপিক ব্রাঞ্চে দুইটি কমিট করেছে এবং সদ্যমাত্র পুশ করেছে। তিনি এটি রান করতে পারেনঃ
				
					$ git request-pull origin/master myfork
The following changes since commit 1edee6b1d61823a2de3b09c160d7080b8d1b3a40:
Jessica Smith (1):
        Create new function

are available in the git repository at:

  git://githost/simplegit.git featureA

Jessica Smith (2):
      Add limit to log function
      Increase log output to 30 from 25

 lib/simplegit.rb |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)
				
			
এই আউটপুটটি মেইন্টেইনারদের কাছে পাঠানো যেতে পারে — কোথা থেকে কাজ গুলোর ব্রাঞ্চ হয়েছে, কমিটগুলো সামারাইজ করে এবং কোথায় নতুন কাজগুলো পুল করা হয়েছে তা আইডেন্টিফাই করে।

যেকোন একটি প্রোজেক্টে আপনি যদি মেইন্টেইনার না হন, তাহলে সাধারণত একটি মেইন ব্রাঞ্চ (যেমন master) রাখা উচিৎ যা সবসময় origin/master কে ট্র্যাক করে এবং আপনার কাজগুলো টপিক ব্রাঞ্চ এ রাখা উচিৎ যাতে যেকোন সময় এটি ডিসকার্ড করা যায় যদি তা রিজেক্টেড হয়। যদি মেইন রিপোজিটরি ইতিমধ্যে সামনে চলে যায়, বা আপডেটেড হয়ে যায় তবে আপনার কমিটগুলো সঠিকভাবে এপ্লাই হবে না। তাই কাজের থিমগুলো ভাগ করে টপিক ব্রাঞ্চ তৈরি করলে কাজগুলোকে সহজভাবে রিবেইজ করা যায়। উদাহরণস্বরূপ, আপনি যদি সেকেন্ড টপিকের কাজটি সাবমিট করতে চান, তবে আপনি টপিক ব্রাঞ্চ এ কাজ করা থেকে বিরত থাকুন যেখানে আপনি সদ্যমাত্র পুশ করেছেন। – আপনি মেইন ব্রাঞ্চ master থেকে পুনরায় শুরু করুনঃ
				
					$ git checkout -b featureB origin/master
  ... work ...
$ git commit
$ git push myfork featureB
$ git request-pull origin/master myfork
  ... email generated request pull to maintainer ...
$ git fetch origin
				
			
এখন আপনার প্রত্যেকটি টপিক একটি silo তে ধারণ করা হয় — patch queue এর মত একই — যে আপনি টপিকগুলোর ইন্টারফেয়ারিং বা ইন্টারডিপেন্ডিং ছাড়াই rewrite করতে পারবেন, রিবেইজ এবং মডিফাই করতে পারবেন।
Figure 69. Initial commit history with featureB work
মনে করুন, প্রোজেক্ট মেইন্টেইনার অন্য কিছু প্যাচ পুল করেছে এবং আপনার প্রথম ব্রাঞ্চটি পুল করার ট্রাই করেছে, কিন্তু এটি আর cleanly মার্জ হচ্ছে না। এই ক্ষেত্রে আপনি আপনার সেই ব্রাঞ্চটি রিবেইজ করতে পারেন origin/master এর উপর। এরপর আপনি কনফ্লিক্টগুলো resolve করে নিন এবং আবার পুনরায় আপনার চেঞ্জগুলো সাবমিট করুনঃ
				
					$ git checkout featureA
$ git rebase origin/master
$ git push -f myfork featureA
				
			

এটি আপনার হিস্টোরিগুলো কে rewrite করে যাতে করে এখন (“featureA work”) এর কাজ  (“Commit history after”) এর মত দেখায়।

এটি আপনার হিস্টোরিগুলো কে rewrite করে যাতে করে এখন (“featureA work”) এর কাজ  (“Commit history after”) এর মত দেখায়।

Figure 70. Commit history after featureA work
যেহেতু আপনি ব্রাঞ্চটি রিবেইজ করেছেন তাই আপনার পুশ কমান্ডে -f অবশ্যই স্পেসিফাই করতে হবে, যাতে আপনার featureA ব্রাঞ্চটি সার্ভারে রিপ্লেস হতে পারে একটি কমিট এর মাধ্যমে যা এর ডিসেন্ডেন্ট নয়। একটি অন্য উপায় হচ্ছে এই নতুন চেঞ্জগুলো একটি নতুন ব্রাঞ্চ এ পুশ করা। (যেমনঃ featureAv2)।

চলুন আরও একটি পসিবল সিনারিও দেখিঃ মেইন্টেইনার আপনার সেকেন্ড ব্রাঞ্চটি দেখলো এবং কন্সেপ্টটি পছন্দ করল, কিন্তু কিছু ইমপ্লিমেন্টেশন ডিটেইল চেঞ্জ করতে বলল। আপনিও অবশ্যই এই সুযোগে প্রোজেক্ট এর বর্তমান master ব্রাঞ্চ থেকে আপনার ব্রাঞ্চটি মার্জ করে নিবেন। আপনি একটি origin/master ব্রাঞ্চ থেকে একটি নতুন ব্রাঞ্চ (featureB) তৈরি করবেন এবং featureB এর চেঞ্জগুলো squash করে নিবেন। এরপর সবগুলো কনফ্লিক্ট resolve করবেন এবং ইম্পিমেন্টেশন চেঞ্জগুলো করুন। সবশেষে এটি নতুন ব্রাঞ্চ হিসেবে পুশ করুন।
				
					$ git checkout -b featureBv2 origin/master
$ git merge --squash featureB
  ... change implementation ...
$ git commit
$ git push myfork featureBv2
				
			
–squash অপশনটি মার্জ করা ব্রাঞ্চের সমস্ত কাজকে একত্র করে নেয় এবং এমন একটি চেঞ্জসেট তৈরি করে যেটি দেখে মনে হয় যে, মার্জ কমিট করা ছাড়াই, একটি সঠিক মার্জ হয়েছে। এর মানে হল আপনার ফিউচার কমিটের শুধু একটি প্যারেন্ট থাকবে এবং এটি অন্য ব্রাঞ্চ থেকে সকল চেঞ্জগুলো কে নিয়ে আসবে এবং এরপর নতুন কমিট করার আগে আরও চেঞ্জ করা যাবে। এছাড়াও ডিফল্ট মার্জ প্রসেস এর ক্ষেত্রে, মার্জ কমিট আরও দেরিতে করার জন্য –no-commit অপশনটি ইউজফুল হতে পারে।

এই পয়েন্টে, আপনি মেইন্টেইনারকে জানাতে পারেন যে, আপনি রিকুয়েস্টেড চেঞ্জগুলো করে ফেলেছেন এবং তারা আপনার সেই চেঞ্জেস গুলো খুজে বের করতে পারবে আপনার featureBv2 এই ব্রাঞ্চটিতে।
Figure 70. Commit history after featureA work

ফর্ক করা পাবলিক প্রোজেক্ট

পাবলিক প্রোজেক্ট এ কন্ট্রিবিউট করা একটু আলাদা। কারণ সরাসরি প্রোজেক্ট এর ব্রাঞ্চে আপনার আপডেট করার অনুমতি নেই। আপনাকে অন্য কোনো উপায়ে মেইন্টেইনারদের কাছে কাজ পাঠাতে হবে। প্রথম উদাহরণটি সহজভাবে ফর্কিং এর মাধ্যমে গিট হোস্ট এ কন্ট্রিবিউট করাকে সমর্থন করে। অনেক হোস্টিং সাইটগুলো এটি সাপোর্ট করে (যেমনঃ GitHub, BitBucket, repo.or.cz এবং আরও অনেক রয়েছে) এবং অনেক প্রোজেক্ট মেইন্টেইনাররা এই কন্ট্রিবিউশনের এই স্টাইলগুলো এক্সপেক্ট করে। পরবর্তী অনুচ্ছেদটি প্রোজেক্টগুলোর সাথে এমনভাবে ডিল করে যা ই-মেইলের মাধ্যমে কন্ট্রিবিউটেড প্যাচ গ্রহণ প্রেফার করে।

প্রথমত আপনি হয়তো মেইন রিপোজিটরি ক্লোন করতে পছন্দ করবেন। একটি প্যাচ বা প্যাচ সিরিজ এর জন্য একটি টপিক ব্রাঞ্চ তৈরি করুন, যেটি আপনি প্ল্যান করেছেন এবং সেখানে আপনার প্রেফারেবল কাজগুলো করুন। এই সিকুন্সটি সাধারণত এরকম হয়ঃ
				
					$ git checkout -b topicA
  ... work ...
$ git commit
  ... work ...
$ git commit
				
			
এখন আপনার দুটি কমিট আছে যেটি আপনি মেইলিং লিস্ট এ সেন্ড করতে চান। mbox-formatted ফাইলগুলো জেনারেট করার জন্য আপনি git format-patch ইউজ করবেন যাতে আপনি লিস্ট এ ইমেইল করতে পারেন। — এটি প্রত্যেকটি কমিটকে একটি ইমেইল মেসেজ এ কনভার্ট করে। এই মেসেজটি কমিট মেসেজের প্রথম লাইনটি সাবজেক্ট হিসেবে নেয় এবং বাকি সব মেসেজগুলো ইমেইল বডি হিসেবে নেয়। এটার সবচেয়ে ভালো দিক হলো ইমেইল জেনারেটেড একটি প্যাচ format-patch এর মাধ্যমে এপ্লাই করলে সকল কমিট ইনফরমেশনগুলো সঠিকভাবে প্রিজার্ভ হয়।
				
					$ git format-patch -M origin/master
0001-add-limit-to-log-function.patch
0002-increase-log-output-to-30-from-25.patch

				
			
Format-patch কমান্ডটি প্যাচ ফাইলের নামগুলো প্রিন্ট করে। -M switch-টি গিট কে rename করার জন্য দেখতে বলে। এই ফাইলগুলো এইরকম দেখতেঃ
				
					$ cat 0001-add-limit-to-log-function.patch
From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
From: Jessica Smith <jessica@example.com>
Date: Sun, 6 Apr 2008 10:17:23 -0700
Subject: [PATCH 1/2] Add limit to log function

Limit log functionality to the first 20

---
 lib/simplegit.rb |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index 76f47bc..f9815f1 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -14,7 +14,7 @@ class SimpleGit
   end

   def log(treeish = 'master')
-    command("git log #{treeish}")
+    command("git log -n 20 #{treeish}")
   end

   def ls_tree(treeish = 'master')
--
2.1.0

				
			
ইমেইল লিস্ট এ যাতে না দেখায়, তার জন্য আরও ইনফরমেশন এড করতে হলে আপনি এই প্যাচ ফাইলগুলো এডিট করতে পারবেন। আপনি যদি – – – লাইন এবং “প্যাচ শুরুর সময়” এ দুটির মাঝে যদি টেক্সট এড করেন (the diff –git লাইন), তাহলে ডেভেলপাররা এটি পড়তে পারবে। কিন্তু এই কন্টেন্ট প্যাচিং প্রোসেস এ ইগ্নোর হবে।

মেইলিং লিস্ট এ ইমেইল করার জন্য, হয় আপনি আপনার ইমেইল প্রোগ্রাম এ ফাইলটি পেস্ট করবেন অথবা একটি command-line program এর মাধ্যমে সেন্ড করবেন। পেস্ট করলে সবসময় ফরমেটিং ইস্যু হয়। বিশেষভাবে “smarter” ক্লায়েন্টগুলোর সাথে যেগুলো নিউ লাইন এবং অন্যান্য হোয়াইট স্পেস সঠিকভাবে প্রিজার্ভ করে না। কপালগুনে, গিট এমন একটি tool প্রোভাইড করে যাতে আপনি IMAP এর মাধ্যমে সঠিকভাবে ফরমেটেড প্যাচগুলো পাঠাতে পারেন। এটি আপনার জন্য খুবই সহজ হবে। আমরা দেখাবো কিভাবে একটি প্যাচ Gmail এর মাধ্যমে পাঠাতে হয়। আপনি ডিটেইল ইন্সট্রাকশন পড়ে দেখতে পারেন সবশেষে মেনশন করা আছে গিট সোর্স এর Documentation/SubmittingPatches ফাইলে। প্রথমে ~/.gitconfig ফাইল এ আপনাকে IMAP সেকশনটি সেট আপ করতে হবে । আপনি প্রত্যেকটি ভ্যালু আলাদাভাবে সেট করতে পারবেন git config সিরিজ এর কমান্ডগুলোর মাধ্যমে অথবা আপনি ম্যানুয়ালি এড করতে পারবেন। কিন্তু পরিশেষে আপনার কনফিগ ফাইলটি এরকম দেখতে হবেঃ
				
					[imap]
  folder = "[Gmail]/Drafts"
  host = imaps://imap.gmail.com
  user = user@gmail.com
  pass = YX]8g76G_2^sFbd
  port = 993
  sslverify = false

				
			
যদি আপনার IMAP সার্ভারটি SSL ইউজ না করে থাকে, তাহলে শেষ দুইটি লাইন জরুরী নয় এবং হোস্ট ভ্যালুটি imaps:// এর পরিবর্তে imap:// হবে। যখন এটি সেট আপ হয়ে যাবে তখন আপনি স্পেসিফাইড IMAP সার্ভারের Drafts ফোল্ডারের প্যাচ সিরিজ প্লেস করার জন্য git imap-send কমান্ডটি রান করবেন।
				
					$ cat *.patch |git imap-send
Resolving imap.gmail.com... ok
Connecting to [74.125.142.109]:993... ok
Logging in...
sending 2 messages
100% (2/2) done
				
			
এই পয়েন্টে আপনি আপনার Drafts ফোল্ডারে যেতে পারবেন, মেইলিং লিস্ট এ To নামক ফিল্ডটি চেঞ্জ করতে পারবেন এবং সম্ভব হলে মেইন্টেইনারকে CC হিসেবে দিতে পারবেন এবং সেন্ড করতে পারবেন।

আপনি SMTP সার্ভারের মাধ্যমেও প্যাচগুলো সেন্ড করতে পারবেন। আগের মতই আপনি প্রত্যেক ভ্যালু আলাদা ভাবে সেট আপ করতে পারবেন git – – config কমান্ড সিরিজ এর মাধ্যমে অথবা সেন্ড মেইল সেকশনে ম্যানুয়ালি এড করতে পারবেন ~/.gitconfig ফাইল এ।
				
					[sendemail]
  smtpencryption = tls
  smtpserver = smtp.gmail.com
  smtpuser = user@gmail.com
  smtpserverport = 587
				
			
এটি শেষ করার পর আপনি git send-email এই কমান্ড টি রান করতে পারবেন।
				
					$ git send-email *.patch
0001-add-limit-to-log-function.patch
0002-increase-log-output-to-30-from-25.patch
Who should the emails appear to be from? [Jessica Smith <jessica@example.com>]
Emails will be sent from: Jessica Smith <jessica@example.com>
Who should the emails be sent to? jessica@example.com
Message-ID to be used as In-Reply-To for the first email? Y
				
			
এরপর গিট কিছু লগ ইনফরমেশন দেয় যেটি অনেকটা এইরকম দেখতে হয়ঃ
				
					(mbox) Adding cc: Jessica Smith <jessica@example.com> from
  \line 'From: Jessica Smith <jessica@example.com>'
OK. Log says:
Sendmail: /usr/sbin/sendmail -i jessica@example.com
From: Jessica Smith <jessica@example.com>
To: jessica@example.com
Subject: [PATCH 1/2] Add limit to log function
Date: Sat, 30 May 2009 13:29:15 -0700
Message-Id: <1243715356-61726-1-git-send-email-jessica@example.com>
X-Mailer: git-send-email 1.6.2.rc1.20.g8c5b.dirty
In-Reply-To: <y>
References: <y>

Result: OK
				
			
টিপ

For help on configuring your system and email, more tips and tricks, and a sandbox to send a trial patch via email, go to git-send-email.io.

সারমর্ম

এই অনুচ্ছেদে, আমরা ছোট টিম এর অংশ হিসেবে closed-source প্রজেক্টে কাজ করা বা বড় পাবলিক প্রজেক্টে কোলাবোরেট করার মধ্যে পার্থক্যের ব্যাপারে বিবরণ দেয়া হয়েছে। কমিট করার আগে ওয়াইট-স্পেস ত্রুটি পরীক্ষা করতে হবে এবং একটি ভাল কমিট মেসেজ লিখতে হবে। প্যাচ ফর্ম্যাট করা এবং একটি ডেভেলপার মেইলিং লিস্টে ই-মেইল কিভাবে প্রেরণ করা হয় তা দেখানো হয়েছে। বিভিন্ন ওয়ার্কফ্লোরের মধ্যে মার্জ করার ব্যাপারেও বিবরণ দেয়া হয়েছে।

পরবর্তীতে, আপনি কয়েনের উল্টো সাইড কিভাবে কাজ করে তা দেখবেন; গিট প্রজেক্ট কিভাবে মেইন্টেইন করতে হয় সেই বিষয়ে জানবেন। আপনি শিখবেন কিভাবে benevolent dictator বা integration manager হওয়া যায়।