৯.১ ক্লায়েন্ট হিসাবে গিট

পৃথিবী নিখুঁত নয়। সাধারণত, আপনি যে সমস্ত প্রোজেক্টে কাজ করেন সেগুলিকে আপনি সাথে সাথে গিট-এ স্যুইচ করতে পারবেন না। কখনও কখনও এমন হয় যে আপনি আপনার প্রোজেক্টে অন্য ভিসিএস(VCS) ব্যবহার করছেন এবং আপনি চান যে এটাকে গিট্ এ পরিবর্তন করতে । আপনি যে প্রোজেক্টে কাজ করছেন সেটি ভিন্ন সিস্টেমে হোস্ট করা হলে আমরা এই অধ্যায়ের প্রথম অংশটিতে সেই প্রোজেক্টে ক্লায়েন্ট হিসেবে Git ব্যবহার করার উপায় সম্পর্কে শিখতে পারব।

একটা সময়, আপনি আপনার প্রজেক্টটি গিটে রূপান্তর করতে চাইতে পারেন। এই অধ্যায়ের দ্বিতীয় অংশটি আপনার প্রজেক্টটি কিভাবে বিভিন্ন নির্দিষ্ট সিস্টেম থেকে গিট-এ স্থানান্তর করা যায় সেই বিষয়ে আলোচনা করবে এবং যদি কোনো প্রি বিল্ট ইম্পোর্ট টুল (pre-built import tool) না থাকে এমন একটি পদ্ধতি সম্পর্কেও আলোচনা করবে।

ক্লায়েন্ট হিসাবে গিট

গিট ডেভেলপারদের জন্য এত সুবিধাজনক যে অনেকে তাদের ওয়ার্কস্টেশনে এটি ব্যবহার করে, এমনকি যখন তাদের দলের বাকিরা সম্পূর্ণ ভিন্ন ভিসিএস ব্যবহার করে।

গিট এবং সাবভার্সন

ওপেন সোর্স(open source) ডেভেলপমেন্ট প্রজেক্টের একটি বড় অংশ এবং অনেক কর্পোরেট প্রজেক্ট তাদের সোর্স কোড(source code) পরিচালনা করতে সাবভারসন(Subversion) ব্যবহার করে। এটি প্রায় এক দশকেরও বেশি সময় ধরে চলছে, এবং বেশিরভাগ সময়ই ওপেন সোর্স প্রকল্পগুলির জন্য এটি প্রথম পছন্দ ছিল। এটি অনেকটা CVS-এর মত, যা তার আগে সোর্স-কন্ট্রোল জগতের উল্ল্যেখযোগ্য একটি নাম ছিল।

গিট-এর দুর্দান্ত বৈশিষ্ট্যগুলির মধ্যে একটি হল সাবভারশন-এ কাজ করার মতো একটি দ্বিমুখী সেতু(Bi-directional bridge) যাকে গিট এসভিএন(git svn) বলা হয়। এই টুলটি আপনাকে একটি সাবভার্সন সার্ভারে ক্লায়েন্ট হিসাবে গিট ব্যবহার করতে দেয়, যাতে আপনি গিট-এর সমস্ত লোকাল ফিচার ব্যবহার করতে পারেন এবং পরবর্তীতে সব একটি সাবভার্সন সার্ভারে সংরক্ষণ করতে পারেন, ঠিক যেন আপনি সাবভার্সনই ব্যবহার করছেন। অর্থাৎ আপনি লোকাল ব্রাঞ্চ এর কাজ, মার্জিং , স্টেজিং এরিয়া ব্যবহার, রিবেজিং এবং চেরি পিকিং এর মতো কাজ গিট্ এর মাধ্যমে করতে পারবেন সাবভার্সন এর সার্ভার এ, যখন কিনা আপনার সহকর্মীরা আগের কঠিন পদ্ধতিতে কাজ করতে থাকবে। এটা আমার কর্মক্ষেত্রে গিট্ ব্যবহার শুরু করার দিকে একটি ভাল উপায়। সাবভার্সন ব্রিজ হল DVCS জগতের গেটওয়ে ড্রাগ।

git svn

সমস্ত সাবভারশন ব্রিজিং কমান্ডের জন্য গিটে বেস কমান্ড হল git svn। এটি বেশ কয়েকটি কমান্ড নিয়ে কাজ করে, আমরা সবচেয়ে বেশ ব্যবহার হয় কয়েকটি কমান্ড দেখবো।

এটি মনে রাখা জরুরি যে আপনি যখন গিট এসভিএন ব্যবহার করছেন, আপনি সাবভারশনের সাথে ইন্টারঅ্যাক্ট করছেন, এটি এমন একটি সিস্টেম যা গিট থেকে খুব আলাদাভাবে কাজ করে।যদিও আপনি লোকাল ব্রাঞ্চিং এবং মার্জ করতে পারেন, তবে সাধারণত আপনার কাজকে রিবেস করে আপনার ইতিহাসকে যতটা সম্ভব লিনিয়ার (Linear History) রাখা এবং গিট রিমোট রিপোজিটরির সাথে একই সাথে ইন্টারঅ্যাক্ট করার মতো জিনিসগুলি এড়িয়ে যাওয়া সবচেয়ে ভাল।

আপনার ইতিহাস বার বার পরিবর্তন করে পুশ করার চেষ্টা করবেন না এবং একই সময়ে অন্যান্য ডেভেলপারদের সাথে কাজ করার সময় সমান্তরাল গিট রিপোসিটোরিতে পুশ করবেন না। সাবভার্সনের শুধুমাত্র একটি একক লিনিয়ার ইতিহাস(Linear History) থাকতে পারে এবং ভুল হওয়া খুবই সহজ। আপনি যদি একটি দলের সাথে কাজ করছেন, এবং কেউ কেউ SVN ব্যবহার করছেন এবং অন্যরা Git ব্যবহার করছেন, নিশ্চিত করুন যে সবাই কাজ একত্র করার জন্য SVN সার্ভার ব্যবহার করছে – এটি আপনার কাজ সহজ করে তুলবে।

সেটাপ করা

এটি হাতে কলমে করে দেখার জন্য আপনার একটি সাধারণ SVN রিপোসিটোরি প্রয়োজন যেখানে আপনার রাইট অ্যাক্সেস(write access) আছে। আপনি যদি এই উদাহরণটি করে দেখতে চান তবে আপনাকে একটি SVN টেস্ট রিপোসিটোরির এমন একটি কপি লাগবে যেটা রাইট করার এক্সেস আপনার আছে। এটি সহজে করার জন্য, আপনি svnsync নামক একটি টুল ব্যবহার করতে পারেন যা সাবভারশনের সাথে আসে।

উদাহরণটি অনুসরণ করতে, আপনাকে প্রথমে একটি নতুন লোকাল সাবভার্সন রিপোসিটোরি তৈরি করতে হবে:
				
					$ mkdir /tmp/test-svn
$ svnadmin create /tmp/test-svn
				
			
তারপরে, সমস্ত ব্যবহারকারীকে revprops পরিবর্তন করার এক্সেস দিতে হবে – সহজ উপায় হল একটি pre-revprop-change স্ক্রিপ্ট যোগ করা যা সবসময় 0 এক্সিট করে:
				
					$ cat /tmp/test-svn/hooks/pre-revprop-change 
#!/bin/sh 
exit 0; 
$ chmod +x /tmp/test-svn/hooks/pre-revprop-change
				
			
আপনি আপনার লোকাল মেশিন থেকে প্রজেক্টটি sync করার svnsync init কমান্ডটি ব্যবহার করতে পারেন।
				
					$ svnsync init file:///tmp/test-svn \
  http://your-svn-server.example.org/svn/
				
			
এটি সিঙ্ক করার জন্য প্রোপারটিস সেট আপ করে। আর আপনি কোড ক্লোন করবেন:
				
					$ svnsync sync file:///tmp/test-svn
Committed revision 1.
Copied properties for revision 1.
Transmitting file data .............................[...]
Committed revision 2.
Copied properties for revision 2.
[...]
				
			
যদিও এই অপারেশনটি মাত্র কয়েক মিনিট সময় নিতে পারে, কিন্তু আপনি যদি লোকাল রিপোজিটরির পরিবর্তে অন্য রিমোট রিপোজিটরিতে মূল রিপোজিটরি কপি করার চেষ্টা করেন, তবে ১০০ টিরও কম কমিট থাকা সত্ত্বেও প্রক্রিয়াটি প্রায় এক ঘন্টা সময় নেবে। সাবভার্সনকে এক বার একটি রিভিশন ক্লোন করতে হবে এবং তারপরে এটিকে অন্য রিপোজিটরিতে পুশ দিতে হবে – এটি অনেক সময় সাপেক্ষ, তবে এটি একমাত্র সহজ উপায়।

শুরু করার সময়

এখন আপনার কাছে একটি সাবভারশন রিপোজিটরি রয়েছে যেখানে আপনার রাইট অ্যাক্সেস রয়েছে, আপনি এখন একটি সাধারণ ওয়ার্কফ্লো দিয়ে যেতে পারেন। আপনি git svn ক্লোন কমান্ড দিয়ে শুরু করবেন, যা একটি লোকাল গিট রিপোসিটরিতে একটি সম্পূর্ণ সাবভার্সন রিপোসিটরি ইম্পোর্ট করে। মনে রাখবেন যে আপনি সত্যিকারের হোস্ট করা সাবভার্সন রিপোজিটরি থেকে যদি ইম্পোর্ট করেন, তাহলে আপনার সাবভার্সন রিপোজিটরির URL দিয়ে এখানে file:///tmp/test-svn প্রতিস্থাপন করবেন।
				
					$ git svn clone file:///tmp/test-svn -T trunk -b branches -t tags
Initialized empty Git repository in /private/tmp/progit/test-svn/.git/
r1 = dcbfb5891860124cc2e8cc616cded42624897125 (refs/remotes/origin/trunk)
    A	m4/acx_pthread.m4
    A	m4/stl_hash.m4
    A	java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
    A	java/src/test/java/com/google/protobuf/WireFormatTest.java
...
r75 = 556a3e1e7ad1fde0a32823fc7e4d046bcfd86dae (refs/remotes/origin/trunk)
Found possible branch point: file:///tmp/test-svn/trunk => file:///tmp/test-svn/branches/my-calc-branch, 75
Found branch parent: (refs/remotes/origin/my-calc-branch) 556a3e1e7ad1fde0a32823fc7e4d046bcfd86dae
Following parent with do_switch
Successfully followed parent
r76 = 0fb585761df569eaecd8146c71e58d70147460a2 (refs/remotes/origin/my-calc-branch)
Checked out HEAD:
  file:///tmp/test-svn/trunk r75
				
			
এটি আপনার দেওয়া URL-এ, এই দুটি কমান্ড চালায় – git svn init এর পরে git svn fetch – । . এটি অনেক সময় নিতে পারে. যদি, উদাহরণস্বরূপ, টেস্ট প্রজেক্টটিতে মাত্র 75টি কমিট থাকে এবং কোডবেসটি ততটা বড় না হয়, তবুও গিটকে অবশ্যই প্রতিটি সংস্করণ একবারে একবার পরীক্ষা করে দেখতে হবে এবং এটি পৃথকভাবে কমিট করতে হবে। শত শত বা হাজার হাজার কমিট সহ একটি প্রজেক্টের জন্য, এটি আক্ষরিকভাবে শেষ হতে কয়েক ঘন্টা বা এমনকি দিনও সময় লাগতে পারে।

অংশটি -T trunk -b branches -t tagsগিটকে বলে যে এই সাবভার্সন রিপোজিটরিটি বেসিক ব্র্যাঞ্চিঙ এবং ট্যাগিং নিয়মাবলী অনুসরণ করে। আপনি যদি আপনার ট্রাঙ্ক, ব্রাঞ্চ বা ট্যাগের নাম অন্যভাবে রাখেন, আপনি এই অপশনগুলি পরিবর্তন করতে পারেন। যেহেতু এটি খুবই সাধারণ, আপনি এই সম্পূর্ণ অংশটিকে -s দিয়ে প্রতিস্থাপন করতে পারেন, যা স্ট্যান্ডার্ড লেআউট এবং অপশনগুলোকে বোঝাবে। নিম্নলিখিত কমান্ডগুলো সমতুল্য:
				
					$ git svn clone file:///tmp/test-svn -s
				
			
এটি আপনার দেওয়া URL-এ, এই দুটি কমান্ড চালায় – git svn init এর পরে git svn fetch – । . এটি অনেক সময় নিতে পারে. যদি, উদাহরণস্বরূপ, টেস্ট প্রজেক্টটিতে মাত্র 75টি কমিট থাকে এবং কোডবেসটি ততটা বড় না হয়, তবুও গিটকে অবশ্যই প্রতিটি সংস্করণ একবারে একবার পরীক্ষা করে দেখতে হবে এবং এটি পৃথকভাবে কমিট করতে হবে। শত শত বা হাজার হাজার কমিট সহ একটি প্রজেক্টের জন্য, এটি আক্ষরিকভাবে শেষ হতে কয়েক ঘন্টা বা এমনকি দিনও সময় লাগতে পারে।

অংশটি -T trunk -b branches -t tagsগিটকে বলে যে এই সাবভার্সন রিপোজিটরিটি বেসিক ব্র্যাঞ্চিঙ এবং ট্যাগিং নিয়মাবলী অনুসরণ করে। আপনি যদি আপনার ট্রাঙ্ক, ব্রাঞ্চ বা ট্যাগের নাম অন্যভাবে রাখেন, আপনি এই অপশনগুলি পরিবর্তন করতে পারেন। যেহেতু এটি খুবই সাধারণ, আপনি এই সম্পূর্ণ অংশটিকে -s দিয়ে প্রতিস্থাপন করতে পারেন, যা স্ট্যান্ডার্ড লেআউট এবং অপশনগুলোকে বোঝাবে। নিম্নলিখিত কমান্ডগুলো সমতুল্য:
				
					$ git branch -a
* master
  remotes/origin/my-calc-branch
  remotes/origin/tags/2.0.2
  remotes/origin/tags/release-2.0.1
  remotes/origin/tags/release-2.0.2
  remotes/origin/tags/release-2.0.2rc1
  remotes/origin/trunk
				
			
খেয়াল করুন কিভাবে এই টুলটি রিমোট রেফ হিসাবে সাবভার্সন ট্যাগ পরিচালনা করে। এখন Git প্লাম্বিং কমান্ডের দিকে নজর দেওয়া যাক show-ref:
				
					$ git show-ref
556a3e1e7ad1fde0a32823fc7e4d046bcfd86dae refs/heads/master
0fb585761df569eaecd8146c71e58d70147460a2 refs/remotes/origin/my-calc-branch
bfd2d79303166789fc73af4046651a4b35c12f0b refs/remotes/origin/tags/2.0.2
285c2b2e36e467dd4d91c8e3c0c0e1750b3fe8ca refs/remotes/origin/tags/release-2.0.1
cbda99cb45d9abcb9793db1d4f70ae562a969f1e refs/remotes/origin/tags/release-2.0.2
a9f074aa89e826d6f9d30808ce5ae3ffe711feda refs/remotes/origin/tags/release-2.0.2rc1
556a3e1e7ad1fde0a32823fc7e4d046bcfd86dae refs/remotes/origin/trunk
				
			
যখন এটি একটি গিট সার্ভার থেকে ক্লোন করে তখন গিট এটি করে না। একটি নতুন ক্লোনের পরে ট্যাগ সহ একটি রিপোসিটিরই এমন দেখায়:
				
					$ git show-ref
c3dcbe8488c6240392e8a5d7553bbffcb0f94ef0 refs/remotes/origin/master
32ef1d1c7cc8c603ab78416262cc421b80a8c2df refs/remotes/origin/branch-1
75f703a3580a9b81ead89fe1138e6da858c5ba18 refs/remotes/origin/branch-2
23f8588dde934e8f33c263c6d8359b2ae095f863 refs/tags/v0.1.0
7064938bd5e7ef47bfd79a685a62c1e2649e2ce7 refs/tags/v0.2.0
6dcb09b5b57875f334f61aebed695e2e4193db5e refs/tags/v1.0.0
				
			
গিট্ ট্যাগগুলো সরাসরি refs/tags তে এনে রাখে।

সাবভারশনে কমিট করা

এখন যেহেতু আপনার কাছে একটি ওয়ার্কিং ডিরেক্টরি আছে, আপনি প্রজেক্ট এ কিছু কাজ করতে পারেন এবং আপনার কমিটিগুলোকে আপস্ট্রিমে পুশ করতে পারেন, SVN ক্লায়েন্ট হিসাবে গিটকে ব্যবহার করে । আপনি যদি ফাইলগুলির একটি পৰিৱৰ্তন করেন এবং এটি কমিট করেন তবে আপনার কাছে একটি কমিটি রয়েছে যা লোকাল গিট-এ আছে কিন্তু সাবভার্সন সার্ভারে নেই:
				
					$ git commit -am 'Adding git-svn instructions to the README'
[master 4af61fd] Adding git-svn instructions to the README
 1 file changed, 5 insertions(+)
				
			
পরবর্তীতে, আপনি আপনার পরিবর্তন আপস্ট্রিম এ পুশ করতে চান। এটি সাবভারশনে আপনার কাজ করার পদ্ধতিটি কীভাবে পরিবর্তন করে তা লক্ষ্য করুন – আপনি অফলাইনে বেশ কয়েকটি কমিট করতে পারেন এবং তারপরে সেগুলিকে একবারে সাবভার্সন সার্ভারে পুশ করে দিতে পারেন। একটি সাবভারসন সার্ভারে পুশ করতে, আপনি git svn dcommit কমান্ডটি ব্যবহার করবেন:
				
					$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
    M	README.txt
Committed r77
    M	README.txt
r77 = 95e0222ba6399739834380eb10afcd73e0670bc5 (refs/remotes/origin/trunk)
No changes between 4af61fd05045e07598c553167e0f31c84fd6ffe1 and refs/remotes/origin/trunk
Resetting to the latest refs/remotes/origin/trunk
				
			
এটি সাবভার্সন সার্ভার এর কোডের উপরে আপনার করা সব কমিট নেয়, প্রতিটির জন্য একটি সাবভার্সন কমিটি দেয় এবং তারপর আলাদা ভাবে চেনার জন্য আপনার লোকাল গিট কমিটি পৰিৱৰ্তন করে। এটি গুরুত্বপূর্ণ কারণ এর অর্থ হল আপনার কমিটিগুলোর জন্য সমস্ত SHA-1 চেকসামগুলি পরিবর্তিত হয়৷ আংশিকভাবে এই কারণে, সাবভার্সন সার্ভারের সাথে একইসাথে আপনার প্রজেক্ট এর গিট-ভিত্তিক রিমোট সংস্করণগুলির সাথে কাজ করা ভাল নয়। আপনি যদি শেষ কমিটটি দেখেন তবে আপনি নতুনটি দেখতে পাবেন যা git-svn-id যোগ করা হয়েছিল:
				
					$ git log -1
commit 95e0222ba6399739834380eb10afcd73e0670bc5
Author: ben <ben@0b684db3-b064-4277-89d1-21af03df0a68>
Date:   Thu Jul 24 03:08:36 2014 +0000

    Adding git-svn instructions to the README

    git-svn-id: file:///tmp/test-svn/trunk@77 0b684db3-b064-4277-89d1-21af03df0a68
				
			
লক্ষ্য করুন SHA-1 চেকসামটি যা 4af61fd, আপনি যখন শুরুতে যখন কমিট করেছিলেন কিন্তু সেটি এখন 95e0222 দিয়ে শুরু কয় ৷ আপনি যদি একটি গিট সার্ভার এবং একটি সাবভার্সন সার্ভার দুইটিতেই পুশ দিতে চান, তাহলে আপনাকে dcommit প্রথমে ( ) সাবভার্সন সার্ভারে করতে হবে, কারণ সেই ক্রিয়াটি আপনার কমিট ডেটা পরিবর্তন করে।

নতুন পরিবর্তন পুল করা

আপনি যদি অন্য ডেভেলপারদের সাথে কাজ করে থাকেন, তাহলে এক পর্যায়ে আপনাদের মধ্যে একজন পুশ দেবে, এবং তারপরে অন্য একজন এমন পরিবর্তন আনার চেষ্টা করবে যা কনফ্লিক্ট তৈরী করবে। যতক্ষণ পর্যন্ত তাদের কাজ আপনি মার্জ করবেন না ততক্ষন আপনার পরিবর্তনটি গ্রহণ হবে না। git svn এ এটি এমন দেখায়:
				
					$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...

ERROR from SVN:
Transaction is out of date: File '/trunk/README.txt' is out of date
W: d5837c4b461b7c0e018b49d12398769d2bfc240a and refs/remotes/origin/trunk differ, using rebase:
:100644 100644 f414c433af0fd6734428cf9d2a9fd8ba00ada145 c80b6127dd04f5fcda218730ddf3a2da4eb39138 M	README.txt
Current branch master is up to date.
ERROR: Not all changes have been committed into SVN, however the committed
ones (if any) seem to be successfully integrated into the working tree.
Please see the above messages for details.
				
			
এই পরিস্থিতির সমাধান করার জন্য, আপনি git svn rebase চালাতে পারেন যা সার্ভারের, যে কোনো পরিবর্তন যা আপনার কাছে এখনো নেই এবং সার্ভারে যা আছে তা নিয়ে আসে এবং আপনার কাজকে রিবেস করে:
				
					$ git svn rebase
Committing to file:///tmp/test-svn/trunk ...

ERROR from SVN:
Transaction is out of date: File '/trunk/README.txt' is out of date
W: eaa029d99f87c5c822c5c29039d19111ff32ef46 and refs/remotes/origin/trunk differ, using rebase:
:100644 100644 65536c6e30d263495c17d781962cfff12422693a b34372b25ccf4945fe5658fa381b075045e7702a M	README.txt
First, rewinding head to replay your work on top of it...
Applying: update foo
Using index info to reconstruct a base tree...
M	README.txt
Falling back to patching base and 3-way merge...
Auto-merging README.txt
ERROR: Not all changes have been committed into SVN, however the committed
ones (if any) seem to be successfully integrated into the working tree.
Please see the above messages for details.
				
			
এখন আপনি dcommit করতে পারেন:
				
					$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
    M	README.txt
Committed r85
    M	README.txt
r85 = 9c29704cc0bbbed7bd58160cfb66cb9191835cd8 (refs/remotes/origin/trunk)
No changes between 5762f56732a958d6cfda681b661d2a239cc53ef5 and refs/remotes/origin/trunk
Resetting to the latest refs/remotes/origin/trunk
				
			
উল্লেখ্য যে Git এ যেমন, আপনাকে পুশ দেওয়ার আগে আপস্ট্রিম কাজগুলিকে একত্রিত করতে হয় যা আপনার কাছে এখনও লোকালি নেই, git svn এ আপনি তা করতে পারেন শুধুমাত্র যদি পরিবর্তনগুলি দ্বন্দ্ব হয় (যেমন সাবভারশন কীভাবে কাজ করে)। যদি অন্য কেউ একটি ফাইলে একটি পরিবর্তন ঠেলে দেয় এবং তারপরে আপনি অন্য ফাইলে একটি পরিবর্তন ঠেলে দেন, তাহলে আপনার dcommitভাল কাজ হবে:
				
					$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
    M	configure.ac
Committed r87
    M	autogen.sh
r86 = d8450bab8a77228a644b7dc0e95977ffc61adff7 (refs/remotes/origin/trunk)
    M	configure.ac
r87 = f3653ea40cb4e26b6281cec102e35dcba1fe17c4 (refs/remotes/origin/trunk)
W: a0253d06732169107aa020390d9fefd2b1d92806 and refs/remotes/origin/trunk differ, using rebase:
:100755 100755 efa5a59965fbbb5b2b0a12890f1b351bb5493c18 e757b59a9439312d80d5d43bb65d4a7d0389ed6d M	autogen.sh
First, rewinding head to replay your work on top of it...
				
			
এটি মনে রাখা জরুরি, কারণ এর ফলাফল হল একটি প্রজেক্ট স্টেট যা আপনার কম্পিউটারের কোনোটিতেই ছিল না যখন আপনি পুশ করেছিলেন। যদি পরিবর্তনগুলি ইনকোম্পাটিবল হয় কিন্তু কনফ্লিক্ট না করে, তাহলে আপনি এমন সমস্যা পেতে পারেন যা ধরা কঠিন। এটি একটি গিট সার্ভার ব্যবহার করার চেয়ে আলাদা – গিট-এ, আপনি এটি প্রকাশ করার আগে আপনার ক্লায়েন্ট সিস্টেমে স্টেটটি পরীক্ষা করতে পারেন, কিন্তু SVN-এ, তা সম্ভব নয়।

সাবভার্সন সার্ভার থেকে পরিবর্তন আনতে আপনার এই কমান্ডটি চালানো উচিত, এমনকি যদি আপনি কমিট করতে না চান। git svn fetch এর মাধ্যমে আপনি নতুন ডেটা পেতে পারেন, তবে git svn rebase রিমোট থেকে আনার কাজ এবং লোকাল থেকে কমিট এর কাজ দুটিই করে দেয়।
				
					$ git svn rebase
    M	autogen.sh
r88 = c9c5f83c64bd755368784b444bc7a0216cc1e17b (refs/remotes/origin/trunk)
First, rewinding head to replay your work on top of it...
Fast-forwarded master to refs/remotes/origin/trunk.
				
			
মাঝে মাঝে git svn rebase চালানো নিশ্চিত করে যে আপনার কোড আপ টু ডেট আছে। আপনি যখন এটি চালাবেন তখন আপনার ওয়ার্কিং ডিরেক্টরিটি ক্লিন কিনা তা নিশ্চিত হওয়া দরকার। আপনার যদি লোকাল কোন পরিবর্তন থাকে, আপনার হয় কাজটি স্ট্যাশ() করতে হবে অথবা সাময়িক ভাবে কমিট করতে হবে, তারপর আপনি git svn rebase কমান্ডটি রান করতে পারবেন, নাহলে রিবেস অপারেশনটি থেমে যাবে যদি কোনো কনফ্লিক্ট পায়।

গিট ব্রাঞ্চ এর সমস্যা

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

ধরুন আপনার ইতিহাস নিচের মত দেখাচ্ছে: আপনি একটি experimentশাখা তৈরি করেছেন, দুটি কমিট করেছেন, এবং তারপরে সেগুলিকে আবার তে মার্জ করেছেন master এ । যখন আপনি dcommit করবেন আপনি এমন আউটপুট দেখতে পাবেন :
				
					$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
    M	CHANGES.txt
Committed r89
    M	CHANGES.txt
r89 = 89d492c884ea7c834353563d5d913c6adf933981 (refs/remotes/origin/trunk)
    M	COPYING.txt
    M	INSTALL.txt
Committed r90
    M	INSTALL.txt
    M	COPYING.txt
r90 = cb522197870e61467473391799148f6721bcf9a0 (refs/remotes/origin/trunk)
No changes between 71af502c214ba13123992338569f4669877f55fd and refs/remotes/origin/trunk
Resetting to the latest refs/remotes/origin/trunk
				
			
মার্জ করা ইতিহাস সহ একটি শাখায় চালানো dcommitঠিকঠাক কাজ করে, কিন্তু আপনি যখন আপনার গিট প্রজেক্টের ইতিহাসটি দেখবেন, তখন দেখবেন এটি আপনার করা একটি কমিটও রিরাইট করেনি experiment- ব্রাঞ্চ-এ, তার পরিবর্তে সব পরিবর্তন একটি কমিট এর SVN ভার্সন এ চলে এসেছে।

যখন অন্য কেউ এই কাজ ক্লোন করবে, তখন তারা দেখবে মার্জ কমিটটিতে সব পরিবর্তন একত্রিত করা, যেন git merge –squash কমান্ডটি রান করা হয়েছে।

সাবভার্সন ব্রাঞ্চিং

সাবভারশনে ব্রাঞ্চিং গিট-এ ব্রাঞ্চিংয়ের মতো নয়; আপনি যদি এটিকে এড়াতে পারেন, তাহলে ভাল। এছাড়া, আপনি সাবভারশন এ করে ব্রাঞ্চ তৈরি করতে এবং কমিটি করতে git svn ব্যবহার করতে পারেন।

একটি নতুন SVN ব্রাঞ্চ তৈরি করা

সাবভারশনে একটি নতুন শাখা তৈরি করতে, আপনাকে git svn branch [new-branch] ব্যবহার করতে হবে:
				
					$ git svn branch opera
Copying file:///tmp/test-svn/trunk at r90 to file:///tmp/test-svn/branches/opera...
Found possible branch point: file:///tmp/test-svn/trunk => file:///tmp/test-svn/branches/opera, 90
Found branch parent: (refs/remotes/origin/opera) cb522197870e61467473391799148f6721bcf9a0
Following parent with do_switch
Successfully followed parent
r91 = f1b64a3855d3c8dd84ee0ef10fa89d27f1584302 (refs/remotes/origin/opera)
				
			
এটি svn copy trunk branches/opera এটি কমান্ডের সমতুল্য কাজ করে এবং কাজটি সাবভার্সন সার্ভারে করে। এটা মনে রাখা গুরুত্বপূর্ণ যে এটি আপনাকে সেই ব্রাঞ্চে চেক আউট করে না; আপনি যদি এই মুহুর্তে কমিটি দেন, তবে সেই কমিটি trunkসার্ভারে যাবে, opera তে নয়।

সক্রিয় ব্রাঞ্চ পরিবর্তন করা

গিট আপনার ইতিহাসে আপনার সাবভার্সন শাখাগুলির যেকোনো একটির টিপ খোঁজার মাধ্যমে আপনার dcommits কোন শাখায় যায় তা বের করে – এবং এটা বর্তমান ব্রাঞ্চ হিস্টোরির শেষে থাকার কথা, একটি git-svn-id সহ।

আপনি যদি একই সাথে একাধিক শাখায় কাজ করতে চান, তাহলে dcommitসেই শাখার জন্য ইম্পোর্ট করা সাবভার্সন কমিট থেকে শুরু করে, নির্দিষ্ট সাবভার্সন ব্রাঞ্চে লোকাল ব্রাঞ্চ সেট আপ করতে পারেন। আপনি যদি একটি operaশাখা চান যেখানে আপনি আলাদাভাবে কাজ করবেন, তাহলে আপনি এই কমান্ড চালাতে পারেন:
				
					$ git branch opera remotes/origin/opera
				
			
এখন, আপনি যদি আপনার operaশাখাকে trunk(আপনার masterশাখায়) একত্রিত করতে চান তবে আপনি এটি করতে পারেন git merge করে। কিন্তু আপনাকে একটি বর্ণনামূলক কমিটি মেসেজ দিতে হবে ( -m এর মাধ্যমে), নাহলে মার্জ মেসেজটি দরকারী কিছুর পরিবর্তে “Merge branch opera” বলবে।

মনে রাখবেন যে যদিও আপনি git merge ব্যবহার করছেন, এবং মার্জ করা সম্ভবত সাবভারশনের তুলনায় অনেক সহজ হবে (কারণ গিট স্বয়ংক্রিয়ভাবে আপনার জন্য উপযুক্ত মার্জ বেস খুঁজে বের করবে), এটি একটি সাধারণ গিট মার্জ কমিট নয়। আপনাকে এই ডেটাটিকে একটি সাবভার্সন সার্ভারে পুনরায় পুশ করে দিতে হবে যা একাধিক পারেন্টকে ট্র্যাক করে এমন একটি কমিটি পরিচালনা করতে পারে না; তাই, আপনি এটিকে পুশ দেওয়ার পরে, এটি একটি একক কমিটের মতো দেখাবে যা অন্য শাখার সমস্ত কাজকে স্কোয়াশ করে। আপনি একটি শাখাকে অন্য শাখায় মার্জ করার পরে, আপনি সহজে ফিরে যেতে পারবেন না এবং সেই শাখায় কাজ চালিয়ে যেতে পারবেন না, যেমন আপনি সাধারণত গিট-এ করতে পারেন। আপনি যে dcommitকমান্ডটি চালান তা এমন সব তথ্য মুছে দেয় যা কোন শাখায় মার্জ করা হয়েছে তার খোঁজ রাখে, তাই পরবর্তী মার্জ-বেস হিসাব ভুল হবে – dcommit টি আপনারgit mergeফলাফলকে git merge –squash মত করে দেখায় . দুর্ভাগ্যবশত, এই পরিস্থিতি এড়াতে কোন ভাল উপায় নেই – সাবভারসন এই তথ্য সংরক্ষণ করতে পারে না, তাই আপনি যখন এটিকে আপনার সার্ভার হিসাবে ব্যবহার করছেন তখন আপনি সর্বদা এর সীমাবদ্ধতার কারণে সীমাবদ্ধ হয়ে যাবেন। সমস্যা এড়াতে, আপনার লোকাল শাখা (এই ক্ষেত্রে, opera) মুছে ফেলা উচিত এটি ট্রাঙ্কে মার্জ করার পরে।

git svn টুলসেট সাবভার্শনে যা ছিল তার অনুরূপ কিছু সুযোগ সুবিধা সরবরাহ করে Git এ রূপান্তরকে সহজ করতে বেশ কয়েকটি কমান্ড সরবরাহ করে। এখানে কয়েকটি কমান্ড রয়েছে যা আপনাকে সাবভার্শনে ব্যবহার করতে দেয়।

SVN স্টাইল ইতিহাস(History)

আপনি যদি সাবভার্সন-এ অভ্যস্ত হন এবং SVN আউটপুট স্টাইলে আপনার ইতিহাস(history) দেখতে চান তবে আপনি SVN ফর্ম্যাটে আপনার commit ইতিহাস(History) দেখতে git svn log চালাতে পারেন:
				
					$ git svn log
------------------------------------------------------------------------
r87 | schacon | 2014-05-02 16:07:37 -0700 (Sat, 02 May 2014) | 2 lines

autogen change

------------------------------------------------------------------------
r86 | schacon | 2014-05-02 16:00:21 -0700 (Sat, 02 May 2014) | 2 lines

Merge branch 'experiment'

------------------------------------------------------------------------
r85 | schacon | 2014-05-02 16:00:09 -0700 (Sat, 02 May 2014) | 2 lines

updated the changelog
				
			
git svn log সম্পর্কে আপনার দুটি গুরুত্বপূর্ণ জিনিস জানা উচিত। প্রথমত, এটি অফলাইন কাজ করে, আসল svn log কমান্ডের মত না, যা সাবভার্সন সার্ভারকে ডেটার (Data) জন্য জিজ্ঞাসা করে। দ্বিতীয়ত, এটি কেবল আপনাকে সেই কমিটগুলো (commits) দেখাবে যা আপনি সাবভার্সন সার্ভারে কমিট (committed) করেছেন। স্থানীয় Git কমিটগুলো (commits) যা আপনি কমিট করেননি তা প্রদর্শিত হয় না; এর মধ্যে অন্যরা সাবভার্সন সার্ভারে যে কমিটগুলো (commits) দিয়েছে তাও প্রদর্শিত হবে না। এটি সাবভার্সন সার্ভারে কমিটের সর্বশেষ পরিচিত state এর মতো।

SVN ANNOTATION

git svn log কমান্ডটি svn log কমান্ড অফলাইনকে অনুকরণ করে, আপনি git svn blame [FILE] চালিয়ে svn annotate সমতুল্য পেতে পারেন. আউটপুট দেখতে এরকম:
				
					$ git svn blame README.txt
 2   temporal Protocol Buffers - Google's data interchange format
 2   temporal Copyright 2008 Google Inc.
 2   temporal http://code.google.com/apis/protocolbuffers/
 2   temporal
22   temporal C++ Installation - Unix
22   temporal =======================
 2   temporal
79    schacon Committing in git-svn.
78    schacon
 2   temporal To build and install the C++ Protocol Buffer runtime and the Protocol
 2   temporal Buffer compiler (protoc) execute the following:
 2   temporal
				
			
আবার, এটি কমিটগুলো দেখায় না যা আপনি স্থানীয়ভাবে Git এ করেছিলেন বা এর মধ্যে সাবভার্সনে push দেওয়া হয়েছিল।

SVN সার্ভার তথ্য

আপনি একই ধরণের তথ্যও পেতে পারেন যা আপনাকে svn info , git svn info চালিয়ে দেয়:
				
					$ git svn info
Path: .
URL: https://schacon-test.googlecode.com/svn/trunk
Repository Root: https://schacon-test.googlecode.com/svn
Repository UUID: 4c93b258-373f-11de-be05-5f7a86268029
Revision: 87
Node Kind: directory
Schedule: normal
Last Changed Author: schacon
Last Changed Rev: 87
Last Changed Date: 2009-05-02 16:07:37 -0700 (Sat, 02 May 2009)
				
			
blame এবং log করার মতো, এটি অফলাইনে চালে এবং এটি আপ-টু-ডেট থাকে যখন আপনি সাবভার্সন সার্ভারের সাথে শেষবারের মতো যোগাযোগ করেছিলেন।

যদি আপনি কোনও সাবভার্সন repository ক্লোন করেন যা svn:ignore বৈশিষ্ট্যগুলো যে কোনও জায়গায় সেট করা আছে, আপনি সম্ভবত অনুরূপ .gitignore ফাইল সেট করতে চাইবেন যাতে আপনি দুর্ঘটনাক্রমে এমন ফাইলগুলো কমিট না করেন যা উচিতও না। এই ইস্যুতে সহায়তা করার জন্য git svn এর দুটি কমান্ড রয়েছে. প্রথমটি হ’ল git svn create-ignore, যা স্বয়ংক্রিয়ভাবে আপনার জন্য অনুরূপ .gitignore ফাইলগুলো তৈরি করে যাতে আপনার পরবর্তী কমিটগুলো (commit) অন্তর্ভুক্ত করতে পারে।

দ্বিতীয় কমান্ডটি git svn show-ignore, যা আপনাকে .gitignore ফাইলে রাখতে হবে এমন লাইনগুলো stdout প্রিন্ট করে যাতে আপনার প্রজেক্টের মধ্যে বাদ দেয়া ফাইলগুলো পুনঃনির্দেশ করতে পারেন:
				
					$ git svn show-ignore > .git/info/exclude
				
			
এইভাবে, আপনি .gitignore ফাইলগুলো দিয়ে প্রজেক্টটি জঞ্জাল(litter) করবেন না।আপনি যদি সাবভার্সন দলের একমাত্র Git ব্যবহারকারী হন এবং আপনার সতীর্থরা প্রজেক্টের .gitignore ফাইলগুলো না চায়, তবে এটি একটি ভাল বিকল্প।

Git-Svn সারসংক্ষেপ

git svn টুলস কার্যকরী হয় যদি আপনি সাবভার্সন সার্ভারের আটকে পড়েন বা অন্যথায় একটি ডেভেলোপমেন্ট ইনভাইরোনমেন্টে থাকেন যেখানে সাবভারশন সার্ভার চালানোর প্রয়োজন হয়। আপনার অকেজো Git হিসাবে বিবেচনা করা উচিত, যাহাই হোক না কেন, আপনি ট্রানস্লেশনের এমন সমস্যাগুলোতে আঘাত করবেন যা আপনাকে এবং আপনার সহযোগীদের বিভ্রান্ত করতে পারে। এই ঝামেলা থেকে দূরে থাকার জন্য, এই নির্দেশিকাগুলি অনুসরণ করার চেষ্টা করুন:

  • একটি লিনিয়ার গিট ইতিহাস রাখুন যা git merge দ্বারা তৈরি  মার্জ কমিট ধারণ করে না। আপনার মূললাইন branch এর বাইরে আপনি যে কোনও কাজ পুনরায় Rebase করুন; এটি মার্জ করবেন না।
  • পৃথক Git সার্ভারের উপরে সেট আপ এবং সহযোগিতা করবেন না।  সম্ভবত নতুন ডেভেলপারদের জন্য ক্লোনগুলি গতি বাড়াবে তবে git-svn-id  তে এন্ট্রি নেই এমন কোনও কিছু পুশ (push) দেবেন না। এমনকি আপনি একটি pre-receive  হুক যুক্ত করতে চাইতে পারেন যা প্রতিটি কমিট ম্যাসেজ git-svn-id এর জন্য  চেক করে  এবং এটি ছাড়াই কমিট থাকা পুশগুলি প্রত্যাখ্যান করে।

আপনি যদি এই নির্দেশিকাগুলি অনুসরণ করেন তবে সাবভার্সন সার্ভারের সাথে কাজ করা আরও সহনীয় হতে পারে। তবে, যদি সত্যিকারের Git সার্ভারে চলে যাওয়া সম্ভব হয় তবে এটি করলে আপনার দল আরও অনেক কিছু অর্জন করতে পারবে।