৯.২ গিট এবং অন্যান্য সিস্টেম – গিট-এ মাইগ্রেট করা
গিট এ স্থানান্তর করা
আপনার যদি অন্য একটি কোডবেস ভিসিএস -এ থাকে কিন্তু আপনি গিট ব্যবহার শুরু করার সিদ্ধান্ত নেন, তাহলে আপনাকে অবশ্যই আপনার প্রজেক্টটি অবশ্যই স্থানান্তর করতে হবে। এই অধ্যায়ে সাধারণ সিস্টেমের জন্য কিছু ইম্পোর্টার নিয়ে আলোচনা করা হবে এবং তারপর দেখানো হবে কিভাবে আপনার নিজস্ব কাস্টম ইম্পোর্টার তৈরি করতে হয়। আপনি শিখবেন কীভাবে পেশাদারভাবে ব্যবহৃত এসসিএম সিস্টেম থেকে ডাটা ইম্পোর্ট করতে হয়, কারণ তারা বেশিরভাগ ব্যবহারকারী যারা স্থানান্তর করছে এবং তাদের জন্য হাই-কোয়ালিটি টুলস সহজে পাওয়া যায়।সাবভার্সন
আপনি যদি গিট এসভিএন ব্যবহার সম্পর্কে পূর্ববর্তী সেকশনটি পড়ে থাকেন, তাহলে আপনি সহজেই একটি রিপোজিটোরি গিট এসভিএন ক্লোন করতে সেই নির্দেশাবলী ব্যবহার করতে পারেন। এরপর সাবভার্সন সার্ভার ব্যবহার করা বন্ধ করুন, একটি নতুন গিট সার্ভারে পুশ দিন এবং এটি ব্যবহার করা শুরু করুন। যদি আপনি হিস্টরি চান, তাহলে আপনি যত তাড়াতাড়ি সম্ভব সাবভারসন সার্ভার থেকে ডেটা পুল করে আনতে পারেন (যা কিছু সময় লাগতে পারে)। তবে, ইম্পোর্ট করাটা সঠিক সিধান্ত না, কারণ এটাতে সময় বেশি লাগে। প্রথম সমস্যা অথর এর তথ্য। সাবভার্সনে যাদের সিস্টেমে ইউজার অ্যাকাউন্ট থাকে প্রত্যেকের কমিট রেকর্ড করে রাখা হয়। পূর্ববর্তী সেকশনে উদাহরণগুলি কিছু জায়গায় schacon দেখায়, যেমন ব্লেম আউটপুট এবং git svn log। আপনি যদি এটিকে আরও ভাল গিট অথর এর ডেটাতে ম্যাপ করতে চান তবে আপনার সাবভার্সন ব্যবহারকারীদের থেকে গিট অথর এর কাছে একটি ম্যাপিং প্রয়োজন। user.txt নামে একটি ফাইল তৈরি করুন যাতে এই ম্যাপিং টি এইরকমের হয়:
schacon = Scott Chacon
selse = Someone Else
এসভিএন ব্যবহার করে অথর এর নামের একটি তালিকা পেতে, আপনি এটি রান করতে পারেন:
$ svn log --xml --quiet | grep author | sort -u | \
perl -pe 's/.*>(.*?)<.*/$1 = /'
এটি XML ফর্ম্যাটে লগ আউটপুট তৈরি করে, তারপর অথর এর তথ্য সহ লাইনগুলি রাখে, ডুপ্লিকেটগুলি বাতিল করে, XML ট্যাগগুলি বের করে দেয় ৷ অবশ্যই এটি শুধুমাত্র গ্রেপ, শর্ট এবং পার্ল ইনস্টল সহ একটি মেশিনে কাজ করে। তারপরে, সেই আউটপুটটিকে আপনার user.txt ফাইলে রিডাইরেক্ট করুন যাতে আপনি প্রতিটি এন্ট্রির পাশে একইরকম গিট ব্যবহারকারী ডেটা যোগ করতে পারেন।
বিঃদ্রঃ
আপনি এই ফাইলটি গিট এসভিএন -এ প্রদান করতে পারেন যাতে এটি অথর এর ডেটা আরও সঠিকভাবে ম্যাপ করতে সহায়তা করে। আপনি ক্লোন বা init কমান্ডে –no-metadata পাস করে সাবভার্সন সাধারণত যে মেটাডেটা ইম্পোর্ট করে তা অন্তর্ভুক্ত না করার জন্য আপনি গিট এসভিএন -কে বলতে পারেন। এটি আপনার গিট লগকে ব্লোট করতে পারে এবং এটি কিছুটা অস্পষ্ট করতে পারে।
বিঃদ্রঃ
আপনি যখন গিট রিপোজিটরিতে করা কমিট গুলিকে আসল এসভিএন রিপোজিটরিতে ফিরিয়ে আনতে চান তখন আপনাকে মেটাডেটা রাখতে হবে। আপনি যদি আপনার কমিট লগে সিঙ্ক্রোনাইজেশন না চান, তাহলে নির্দ্বিধায় –no-metadata প্যারামিটারটি বাদ দিন।
এটি আপনার ইম্পোর্ট কমান্ডকে এইরকম দেখায়:
$ git svn clone http://my-project.googlecode.com/svn/ \
--authors-file=users.txt --no-metadata --prefix "" -s my_project
$ cd my_project
এখন আপনার my_project ডিরেক্টরিতে একটি সুন্দর সাবভার্সন ইম্পোর্ট থাকা উচিত। কমিটের পরিবর্তে এটি দেখতে এইরকম:
commit 37efa680e8473b615de980fa935944215428a35a
Author: schacon
Date: Sun May 3 00:12:22 2009 +0000
fixed install - go to trunk
git-svn-id: https://my-project.googlecode.com/svn/trunk@94 4c93b258-373f-11de-
be05-5f7a86268029
তারা দেখতে এরকম :
commit 03a8785f44c8ea5cdb0e8834b7c8e6c469be2ff2
Author: Scott Chacon
Date: Sun May 3 00:12:22 2009 +0000
fixed install - go to trunk
অথর ফিল্ড এখন অনেক ভাল দেখায় এবং git-svn-id ও আর নেই। আপনার এখন post-import ক্লিনআপ করা উচিত এবং আপনার অপ্রয়োজনীয় রেফারেন্সগুলি ক্লিনআপ করা উচিত যা গিট এসভিএন সেট আপ করেছে। প্রথমে আপনি ট্যাগগুলি সরান যাতে তারা রিমোট ব্রাঞ্চ গুলির পরিবর্তে প্রকৃত ট্যাগ হয় এবং তারপরে আপনি বাকি ব্রাঞ্চগুলিকে স্থানান্তরিত করবেন যাতে তারা লোকাল হয়।
ট্যাগগুলোকে সরিয়ে সঠিক গিট ট্যাগ তৈরি করতে, এটি রান করতে পারেন:
$ for t in $(git for-each-ref --format='%(refname:short)' refs/remotes/tags); do git tag ${t/tags\//} $t && git branch -D -r $t; done
এটি রিমোট ব্রাঞ্চ এর রেফারেন্সগুলি নেয় যা refs/remotes/tags/ দিয়ে শুরু হয় এবং সেগুলিকে যথোপযুক্ত আসল (হালকা) ট্যাগ হিসেবে তৈরি করে।
এরপরে, রেফারেন্স/রিমোটের অধীনে বাকি রেফারেন্সগুলিকে লোকাল ব্রাঞ্চ হতে সরান:
$ for b in $(git for-each-ref --format='%(refname:short)' refs/remotes); do git branch $b refs/remotes/$b && git branch -D -r $b; done
এটি ঘটতে পারে যে আপনি কিছু অতিরিক্ত ব্রাঞ্চ দেখতে পাবেন যা @xxx দ্বারা suffixed (যেখানে xxx একটি সংখ্যা), যখন সাবভার্সনে আপনি শুধুমাত্র একটি ব্রাঞ্চ দেখতে পাবেন। এটি আসলে “peg-revisions” নামে একটি সাবভার্সন বৈশিষ্ট্য, যা এমন কিছু যার জন্য গিট সহজভাবে কোন সিনট্যাক্টিক্যাল প্রতিরূপ নেই। সুতরাং, গিট এসভিএন ব্রাঞ্চ নামের সাথে এসভিএন সংস্করণ নম্বর যোগ করে ঠিক একইভাবে যেভাবে আপনি এসভিএন তে এটি লিখেছিলেন সেই শাখার “peg-revisions” এর জন্য। আপনার যদি “peg-revisions” কোনো বিষয়ে আর দরকার না পড়ে, তাহলে কেবল সেগুলি সরিয়ে দিন:
for p in $(git for-each-ref --format='%(refname:short)' | grep @); do git branch -D $p; done
এখন সমস্ত পুরানো ব্রাঞ্চ গুলি আসল গিট ব্রাঞ্চ এবং সমস্ত পুরানো ট্যাগগুলি আসল গিট ট্যাগ।
ক্লিনআপ করার জন্য একটি শেষ জিনিস আছে। দুর্ভাগ্যবশত,গিট এসভিএন ট্রাংক নামে একটি অতিরিক্ত ব্রাঞ্চ তৈরি করে, যা সাবভার্সনের ডিফল্ট ব্রাঞ্চ ম্যাপিং করে, কিন্তু ট্রাংক রেফ মাস্টারের মতো একই জায়গায় নির্দেশ করে। যেহেতু মাস্টারটি আরও গিট রীতিসিদ্ধ, তাই অতিরিক্ত ব্রাঞ্চটি কীভাবে সরিয়ে ফেলা যায় তা এখানে:
$ git branch -d trunk
শেষ জিনিসটি হল আপনার নতুন গিট সার্ভারটিকে রিমোট হিসাবে যুক্ত করুন এবং এটিতে পুশ দিন। এখানে একটি রিমোট হিসাবে আপনার সার্ভার যোগ করার একটি উদাহরণঃ
$ git remote add origin git@my-git-server:myrepository.git
যেহেতু আপনি আপনার সমস্ত ব্রাঞ্চ এবং ট্যাগগুলি উপরে নিতে চান, আপনি এখন এটি রান করতে পারেন:
$ git push origin --all
$ git push origin --tags
আপনার সমস্ত ব্রাঞ্চ এবং ট্যাগ একটি সুন্দর, ক্লিন ইম্পোর্ট দিয়ে আপনার নতুন গিট সার্ভারে রাখা উচিত।
মারকিউরিয়াল
মারকিউরিয়াল এবং গিট এর ভার্সন সংরক্ষন করার জন্যে মুটামুটি একই রকম মডেল ব্যবহার করা হয়। মারকিউরিয়াল থেকে গিট একটু বেশি সহজ। মারকিউরিয়াল থেকে গিট এ একটি রিপোজিটরিকে “hg-fast-export” টুলস ব্যবহার করে মুটামুটি সহজে কনভার্ট করা যায়।
এই কাজ করার জন্যে “hg-fast-export” এর একটি কপি আপনার দরকার হবে।
$ git clone https://github.com/frej/fast-export.git
প্রথম ধাপে একটি মারকিউরিয়াল রিপোজিটরি ক্লোন করা দরকার যেটি আপনি কনভার্ট করতে চানঃ
$ hg clone /tmp/hg-repo
পরবর্তী ধাপ হল একটি অথর ম্যাপিং ফাইল তৈরি করা। মারকিউরিয়াল গিট – এর চেয়ে কিছুটা বেশি ক্ষমাশীল, কি পরিবর্তন করা হবে তা অথর ফিল্ড এ রাখা হবে। সুতরাং ক্লিন হাউজ করার জন্য এটি একটি ভাল সময়। এজন্য ব্যাশ সেল এ এই এক লাইনের কমান্ডটি রান কর।
$ cd /tmp/hg-repo
$ hg log | grep user: | sort | uniq | sed 's/user: *//' > ../authors
এটি কয়েক সেকেন্ড সময় নিবে, এটা নির্ভর করবে আপনার প্রজেক্টের হিস্টরির উপর। তারপরে /tmp/authors ফাইলটি এরকম কিছু দেখাবেঃ
bob
bob@localhost
bob
bob jones company com>
Bob Jones
Joe Smith
এই উদাহরণে, একই ব্যক্তি (Bob) চারটি ভিন্ন নামের অধীনে পরিবর্তনগুলি তৈরি করেছে, যার মধ্যে একটি আসলে সঠিক দেখাচ্ছে এবং যার মধ্যে একটি গিট কমিটের জন্য সম্পূর্ণরূপে ইনভ্যালিড হবে। hg-fast-export আমাদের প্রতিটি লাইনকে একটি রুল এ পরিণত করে এটি ঠিক করতে দেয়: “<input>”=”<output>”, একটি <input> থেকে একটি <output> এ ম্যাপিং করে। <input> এবং <output> স্ট্রিং এর ভিতরে সকল escape sequences পাইথন এনকোডিং string_escape সাপোর্ট করে। যদি অথর ম্যাপিং ফাইলে কোন <input> মিল না থাকে, তাহলে সেই অথর গিটে আনমডিফাইড পাঠানো হবে। যদি সকল ইউজারনেইম ঠিক দেখায় তাহলে আমাদের এই ফাইলটি দরকার হবে না। এই উদাহরণে, আমরা আমাদের ফাইলটি দেখতে চাই:
"bob"="Bob Jones "
"bob@localhost"="Bob Jones "
"bob "="Bob Jones "
"bob jones company com>"="Bob Jones "
একই ধরনের ম্যাপিং ফাইল এর ব্রাঞ্চ এবং ট্যাগের নাম পরিবর্তন করতে ব্যবহার করা যেতে পারে যদি মারকিউরিয়াল নামটি গিট দ্বারা অনুমোদিত না হয়।
পরবর্তী ধাপ হল আমাদের নতুন গিট রিপোজিটরি তৈরি করা এবং এক্সপোর্ট স্ক্রিপ্ট চালানো:
$ git init /tmp/converted
$ cd /tmp/converted
$ /tmp/fast-export/hg-fast-export.sh -r /tmp/hg-repo -A /tmp/authors
-r ফ্ল্যাগটি hg-fast-export কে বলে আমরা যে মারকিউরিয়াল রিপোজিটরি টি কনভার্ট করতে চাই সেটা কোথায় খুজব, এবং -A ফ্ল্যাগটি বলে যে অথর ম্যাপিং ফাইলটি কোথায় পাওয়া যাবে (ব্রাঞ্চ এবং ট্যাগ ম্যাপিং ফাইলগুলি যথাক্রমে -B এবং -T ফ্ল্যাগ দ্বারা নির্দিষ্ট করা হয়)। স্ক্রিপ্টটি মারকিউরিয়াল চেইঞ্জসেট কে পার্স করে এবং সেগুলিকে গিট-এর “fast-import” ফিচার এর জন্য একটি স্ক্রিপ্টে কনভার্ট করে (যা আমরা একটু পরে বিস্তারিত আলোচনা করব)। এটি কিছুটা সময় নেয় (যদিও এটি নেটওয়ার্কের তুলনায় অনেক দ্রুত), এবং আউটপুটটি মোটামুটি এরকম:
$ /tmp/fast-export/hg-fast-export.sh -r /tmp/hg-repo -A /tmp/authors
Loaded 4 authors
master: Exporting full revision 1/22208 with 13/0/0 added/changed/removed files
master: Exporting simple delta revision 2/22208 with 1/1/0 added/changed/removed files
master: Exporting simple delta revision 3/22208 with 0/1/0 added/changed/removed files
[...]
master: Exporting simple delta revision 22206/22208 with 0/4/0 added/changed/removed files
master: Exporting simple delta revision 22207/22208 with 0/2/0 added/changed/removed files
master: Exporting thorough delta revision 22208/22208 with 3/213/0 added/changed/removed files
Exporting tag [0.4c] at [hg r9] [git :10]
Exporting tag [0.4d] at [hg r16] [git :17]
[...]
Exporting tag [3.1-rc] at [hg r21926] [git :21927]
Exporting tag [3.1] at [hg r21973] [git :21974]
Issued 22315 commands
git-fast-import statistics:
---------------------------------------------------------------------
Alloc'd objects: 120000
Total objects: 115032 ( 208171 duplicates )
blobs : 40504 ( 205320 duplicates 26117 deltas of 39602 attempts)
trees : 52320 ( 2851 duplicates 47467 deltas of 47599 attempts)
commits: 22208 ( 0 duplicates 0 deltas of 0 attempts)
tags : 0 ( 0 duplicates 0 deltas of 0 attempts)
Total branches: 109 ( 2 loads )
marks: 1048576 ( 22208 unique )
atoms: 1952
Memory total: 7860 KiB
pools: 2235 KiB
objects: 5625 KiB
---------------------------------------------------------------------
pack_report: getpagesize() = 4096
pack_report: core.packedGitWindowSize = 1073741824
pack_report: core.packedGitLimit = 8589934592
pack_report: pack_used_ctr = 90430
pack_report: pack_mmap_calls = 46771
pack_report: pack_open_windows = 1 / 1
pack_report: pack_mapped = 340852700 / 340852700
---------------------------------------------------------------------
$ git shortlog -sn
369 Bob Jones
365 Joe Smith
এটায় প্রায় সবকিছু আছে। সমস্ত মারকিউরিয়াল ট্যাগগুলি গিট ট্যাগে রূপান্তরিত হয়েছে, এবং মারকিউরিয়াল ব্রাঞ্চ এবং বুকমার্কগুলি গিট ব্রাঞ্চ এ কনভার্ট হয়েছে। এখন আপনি রিপোজিটরিটি কে তার নতুন সার্ভার-সাইড এ পুশ করে দিতে প্রস্তুত:
$ git remote add origin git@my-git-server:myrepository.git
$ git push origin --all
ব্যাজার
ব্যাজার হল অনেকটা গিট-এর মতই এবং এটি একটি ডিভিসিএস (ডিস্ট্রিবিউটেড ভার্সন কন্ট্রোল সিস্টেম) টুল, এবং আমরা একটি গিট রিপোকে খুব সহজেই একটি ব্যাজার গিট-এ রূপান্তর করতে পারি। এটা করার জন্য আমাদের bzr-fastimport প্লাগইন ব্যাবহার করে করতে হবে।
কিভাবে আমরা bzr-fastimport প্লাগিন ব্যাবহার করবো
bzr-fastimport প্লাগিন বিভিন্ন অপারেটিং সিস্টেম এর জন্য ভিন্ন ভিন্ন হয়ে থাকে, যেমনঃ লিনাক্স এবং উইন্ডোজ । প্রথম ক্ষেত্রে, সবচেয়ে সহজ হল bzr-fastimport প্যাকেজ ইনস্টল করা যা সমস্ত প্রয়োজনীয় ডিপেডেন্সি ইনস্টল করবে।
উদাহরণস্বরূপ, Debian এবং Derived দিয়ে :
$ sudo apt-get install bzr-fastimport
RHEL দিয়ে :
$ sudo yum install bzr-fastimport
ফেডোরা, 22 ভার্সন প্রকাশের পর থেকে, নতুন প্যাকেজ ম্যানেজার হল dnf:
$ sudo dnf install bzr-fastimport
প্যাকেজ গুলো ইনস্টল না হলে, আপনি এটি একটি প্লাগইন হিসাবে ইনস্টল করতে পারেন:
$ mkdir --parents ~/.bazaar/plugins # creates the necessary folders for the plugins
$ cd ~/.bazaar/plugins
$ bzr branch lp:bzr-fastimport fastimport # imports the fastimport plugin
$ cd fastimport
$ sudo python setup.py install --record=files.txt # installs the plugin
এই প্লাগইনটি কাজ করার জন্য, আপনার ফাস্ট ইমপোর্ট পাইথন মডিউলেরও প্রয়োজন হবে। এটি ইনস্টল আছে কিনা তা পরীক্ষা করতে পারেন এবং নিম্নলিখিত কমান্ড দিয়ে এটি ইনস্টল করতে পারেন
$ python -c "import fastimport"
Traceback (most recent call last):
File "", line 1, in
ImportError: No module named fastimport
$ pip install fastimport
একটি সিঙ্গেল ব্রাঞ্চ প্রজেক্ট:
এখন আপনার ব্যাজার রিপো রয়েছে এমন ডিরেক্টরিতে চেইঞ্জ ডিরেক্টরি করুন এবং গিট শুরু করুন:
$ cd /path/to/the/bzr/repository
$ git init
এখন, আপনি আপনার ব্যাজার রিপোজিটরি এক্সপোর্ট করতে পারেন এবং নিম্নলিখিত কমান্ড ব্যবহার করে এটিকে একটি গিট রিপোজিটরি রূপান্তর করতে পারেন:
$ bzr fast-export --plain . | git fast-import
এটি সম্পুণ হতে একটু সময় নিতে পারে, এটা প্রোজেক্ট সাইজের উপর নির্ভর করে ।
কেইস অফ এ প্রজেক্ট উইথ এ মেইন ব্রাঞ্চ এন্ড এ ওয়ার্কিং ব্রাঞ্চ:
ধরুন আপনার দুটি ব্রাঞ্ছ আছে একটি হল মেইন ব্রাঞ্চ (myProject.trunk) এবং আর একটি হল ওয়ার্কিং ব্রাঞ্চ (myProject.work) যেটাতে আপনি কাজ করছেন
$ ls
myProject.trunk myProject.work
গিট রিপোজিটরি তৈরি করুন এবং এতে চেইঞ্জ ডিরেক্টরি করুন:
$ git init git-repo
$ cd git-repo
গিটে মাস্টার ব্রাঞ্চ থেকে পুল নিন:
$ bzr fast-export --export-marks=../marks.bzr ../myProject.trunk | \
git fast-import --export-marks=../marks.git
গিটে ওয়ার্কিং ব্রাঞ্চ থেকে পুল নিন:
$ bzr fast-export --marks=../marks.bzr --git-branch=work ../myProject.work | \
git fast-import --import-marks=../marks.git --export-marks=../marks.git
এখ্ন git branch লিখলেই দেখতে পাবো আমাদের দুটি ব্রাঞ্চ দেখাচ্ছে
marks.bzr এবং marks.git
স্টেজিং এরিয়া সিঙ্ক্রোনাইজ করা:
আপনার যতগুলি ব্রাঞ্চ ছিল এবং আপনি যে ইম্পোর্ট পদ্ধতি ব্যবহার করেছেন তা যাই হোক না কেন, আপনার স্টেজিং এরিয়াটি হেড এর সাথে সিঙ্ক্রোনাইজ করা হয় না এবং বেশ কয়েকটি ব্রাঞ্চের ইম্পোর্ট এর সাথে, আপনার কাজের ডিরেক্টরিটিও সিঙ্ক্রোনাইজ করা হয় না। এই পরিস্থিতি সহজেই নিম্নলিখিত কমান্ড দ্বারা সমাধান করা হয়:
$ git reset --hard HEAD
.bzrignor দিয়ে ফাইলগুলিকে ইগনোর করুন:
এখন ফাইলগুলি লক্ষ করে দেখুন। প্রথমে .bzrignore এর নাম পরিবর্তন করে .gitignore করতে হবে। যদি .bzrignore ফাইলে “!!” অথবা “RE:” দিয়ে শুরু হওয়া এক বা একাধিক লাইন থাকে, আপনাকে এটি পরিবর্তন করতে হবে এবং ব্যাজার ইগনোর করা । ঠিক একই ফাইলগুলিকে ইগনোর করার জন্য সম্ভবত বেশ কয়েকটি .gitignore ফাইল তৈরি করতে হবে৷
অবশেষে, আপনাকে একটি কমিট তৈরি করতে হবে মাইগ্রেশনের জন্য
$ git mv .bzrignore .gitignore
$ # modify .gitignore if needed
$ git commit -am 'Migration from Bazaar to Git'
আপনার রিপোজিটরি কে সার্ভারে পুশ করেন।
$ git remote add origin git@my-git-server:mygitrepository.git
$ git push origin --all
$ git push origin --tags
পারফোর্স
পরের যে সিস্টেম থেকে আমরা ইম্পোর্ট করতে পারি তা হল পারফোর্স। উপরোক্ত আলোচনা সাপেক্ষে গিট আর পারফোর্স এর মধ্যে যোগাযোগ এর দুইটা উপায় আছে :
গিট-p4 আর পারফোর্স গিট ফিউশন
পারফোর্স গিট ফিউশন:
গিট ফিউশন এই কাজটি অনেকাংশে সহজ করে তোলে। এর জন্য প্রজেক্ট সেটিংস, ইউজার ম্যাপিং এবং ব্রাঞ্চ গুলা কনফিগার করতে হবে কনফিগারেশন ফাইল (গিট ফিউশন এ বলা হয়েছে) এর সাথে। এরপর রিপোজিটরি টা ক্লোন করে নিতে হবে। গিট ফিউশন একটা নেটিভ রিপোজিটরি করে দেয় যেটা পরবর্তীতে একটা নেটিভ গিট হোস্ট এ আমরা চাইলে পুশ করতে পারি। এমনকি আমরা পারফোর্স কেও গিট হোস্ট হিসেবে ব্যবহার করতে পারি।
গিট-p4:
গিট-p4 একটি ইম্পোর্ট টুল হিসেবেও কাজ করতে পারে। আমরা পারফোর্স পাবলিক ডিপোট থেকে জ্যাম প্রজেক্ট ইম্পোর্ট করব। ক্লায়েন্ট সেটআপ করতে হলে, অবশ্যই P4PORT এনভায়রনমেন্ট ভ্যারিয়েবল এক্সপোর্ট করতে হবে যেটা পারফোর্স ডিপোট কে পয়েন্ট করবে।
$ export P4PORT=public.perforce.com:1666
নোট
ফলো করতে আপনার একটি পারফোর্স ডিপোট লাগবে কানেক্ট করার জন্য। আমরা public.perforce.com এ পাবলিক ডিপোট ব্যবহার করব আমাদের উদাহরণে, কিন্তু আপনি যেকোনো ডিপোট ব্যবহার করতে পারেন যেটায় আপনার অ্যাক্সেস আছে।
জ্যাম প্রজেক্ট কে পারফোর্স server থেকে ইম্পোর্ট করতে git p4 clone কমান্ড টি রান করুন আর এজন্য ডিপোট, প্রজেক্ট পাথ আর যে পাথ – এ প্রজেক্ট টা ইম্পোর্ট করবেন তা সাপ্লাই করতে হবে।
$ git-p4 clone //guest/perforce_software/jam@all p4import
Importing from //guest/perforce_software/jam@all into p4import
Initialized empty Git repository in /private/tmp/p4import/.git/
Import destination: refs/remotes/p4/master
Importing revision 9957 (100%)
এই প্রজেক্ট এ শুধু একটি ব্রাঞ্চ আছে, কিন্তু আপনার যদি অনেক ব্রাঞ্চ থাকে যেগুলা ব্রাঞ্চ ভিউস (অথবা ডিরেক্টরি সেট) দিয়ে কনফিগার করা হয়েছে, আপনি –detect-branches flag ব্যবহার করে git p4 clone করতে পারেন যা প্রজেক্ট এর সব ব্রাঞ্চ গুলা ইম্পোর্ট করবে। আরও বিশদ ভাবে জানার জন্য দেখুন
এই পর্যায়ে আপনার কাজটি প্রায় শেষ। যদি আপনি p4import ডিরেক্টরি তে যান আর রান করেন git log, আপনি আপনার ইম্পোর্ট করা কাজটি দেখবেন :
$ git log -2
commit e5da1c909e5db3036475419f6379f2c73710c4e6
Author: giles
Date: Wed Feb 8 03:13:27 2012 -0800
Correction to line 355; change to .
[git-p4: depot-paths = "//public/jam/src/": change = 8068]
commit aa21359a0a135dda85c50a7f7cf249e4f7b8fd98
Author: kwirth
Date: Tue Jul 7 01:35:51 2009 -0800
Fix spelling error on Jam doc page (cummulative -> cumulative).
[git-p4: depot-paths = "//public/jam/src/": change = 7304]
আপনি খেয়াল করবেন যে, গিট-p4 প্রতিটা কমিট মেসেজ এ একটা আইডেন্টিফায়ার রেখেছে। এই আইডেন্টিফায়ার টি এখানে রাখা যাবে, পরবর্তীতে আপনার পারফোর্স টি রেফারেন্স করা প্রয়োজন হলে নাম্বার টি পরিবর্তন করতে পারেন। কিন্তু আপনি যদি আইডেন্টিফায়ার টি বদলাতে চান, এখনি করা উচিত – নতুন রিপোজিটরি তে কাজ শুরু করার আগে। আপনি git filter-branch ব্যবহার করে আইডেন্টিফায়ার এন মেস সরাতে পারেনঃ
$ git filter-branch --msg-filter 'sed -e "/^\[git-p4:/d"'
Rewrite e5da1c909e5db3036475419f6379f2c73710c4e6 (125/125)
Ref 'refs/heads/master' was rewritten
যদি আপনি git log run করেন, আপনি দেখবেন যে কমিট গুলার সব SHA-1 চেকসাম পরিবর্তন হয়েছে, কিন্তু গিট-p4 স্ট্রিং গুলা কমিট মেসেজ এ আর নেই :
$ git log -2
commit b17341801ed838d97f7800a54a6f9b95750839b7
Author: giles
Date: Wed Feb 8 03:13:27 2012 -0800
Correction to line 355; change to .
commit 3e68c2e26cd89cb983eb52c024ecdfba1d6b3fff
Author: kwirth
Date: Tue Jul 7 01:35:51 2009 -0800
Fix spelling error on Jam doc page (cummulative -> cumulative).
আপনার ইম্পোর্ট আপনার নতুন গিট সার্ভারে পুশ করার জন্য রেডি।
কাস্টম ইম্পোর্টার:
যদি আপনার সিস্টেম উপরের কোনোটিই না হয়ে থাকে, সেক্ষেত্রে আপনাকে একটি অনলাইন ইম্পোর্টার খুঁজতে হবে- এধরনের অনেক ইম্পোর্টার আছে যা সহজলভ্য এবং বিভিন্ন সিস্টেমের জন্য তা পার্ফেক্ট, এসব সিস্টেমের অন্তর্ভুক্ত সিভিএস, ক্লিয়ার কেইস, ভিজুয়াল সোর্স সেফ, এমনকি আর্কাইভ ডিরেক্টরি। যদি এসব টুল বা সিস্টেমের কোনোটাই আপনার না থেকে থাকে, তাহলে আপনার একটি কাস্টম ইম্পোর্টিং প্রসেস অনুসরণ করতে হবে, এজন্য ইউজ করুন
git fast-import
এই কমান্ডটি স্পেসিফিক গিট ডাটা রাইট করতে stdin থেকে কিছু সিম্পল ইনস্ট্রাকশনস রিড করে। র-গিট কমান্ডস রান করানোর চেয়ে কিংবা র অবজেক্ট রাইট করার চেয়ে এই উপায়ে গিট অবজেক্ট ক্রিয়েট করা বেশি সহজ।(আরো তথ্য পেতে ক্লিক করুন গিট ইন্টারনালস)। এভাবে আপনি সহজেই একটি ইম্পোর্ট স্ক্রিপ্ট লিখে ফেলতে পারেন যা আপনার সিস্টেম (যা থেকে ইম্পোর্ট করতে হবে) থেকে প্রয়োজনীয় ইনফরমেশন রিড করে আনতে পারে এবং stdout এ সরাসরি ইন্সট্রাকশন হিসেবে প্রিন্ট করে। এরপর আপনি প্রোগ্রামটি রান করতে পারবেন এবং আউটপুটটি git fast-import এর মাধ্যমে অন্য কমান্ড এর ইনপুট হিসেবে ব্যবহার করতে পারবেন।
সহজে বলতে গেলে, আপনি একটি সিম্পল ইম্পোর্টার লিখবেন। মনে করুন আপনি কারেন্ট এ কাজ করছেন, আপনি আপনার প্রজেক্ট মাঝে মাঝে কপি করে একটি time-stamped back_YYYY_MM_DD ব্যাকাপ ডিরেক্টরি তে কপি করে ব্যাকাপ হিসেবে রাখেন, এখন আপনি চাচ্ছেন আপনার প্রজেক্ট কে গিট এ ইম্পোর্ট করতে। আর আপনার ডিরেক্টরির স্ট্রাকচার নিচের মতঃ
$ ls /opt/import_from
back_2014_01_02
back_2014_01_04
back_2014_01_14
back_2014_02_03
current
একটি গিট ডিরেক্টরি ইম্পোর্ট করতে হলে আগে জানতে হবে গিট কিভাবে এর ডাটা সংরক্ষণ করে। আশা করি আপনার মনে আছে যে, গিট মূলত কমিট অবজেক্ট এর একটি লিঙ্কড লিস্ট যা একটি কন্টেন্ট এর স্ন্যাপশট (সার্ভার রেসপন্সের কপি) কে নির্দেশ করে। আপনাকে যা করতে হবে তা হলো fast-import কে কন্টেন্ট এর স্ন্যাপশট গুলো বলে দেয়া, কোন কমিট ডাটা তাদেরকে নির্দেশ করছে এবং লিস্টে তারা কি অর্ডার মেইনটেইন করছে। আপনার স্ট্রাটেজি হবে প্রতিটি স্ন্যাপশট বিবেচনা করে প্রতিটি ডিরেক্টরির কন্টেন্টে কমিট ক্রিয়েট করা যাতে প্রতিটি কমিট তার পূর্ববর্তী কমিট এর সাথে লিঙ্কড থাকে।
আমরা দেখেছি একটি গিট-এনফোর্সড পলিসির উদাহরণ, আমরা তা রুবী তে লিখবো, কারণ সাধারণত আমরা রুবী তে কাজ করি কারণ এটি সহজবোধ্য। আপনি চাইলে আপনার পরিচিত যেকোনো ল্যাংগুয়েজে উদাহরণটি করে দেখতে পারেন। এর জন্য দরকার শুধু সঠিক ইনফরমেশন গুলো stdout. এ প্রিন্ট হতে হবে। আর যদি আপনি উইন্ডোজ এ রান করে থাকেন, তার মানে আপনাকে সতর্ক থাকতে হবে যাতে লাইনের শেষে ক্যারিয়েজ রিটার্ন না করে, এক্ষেত্রে git fast-import খুবই হেল্পফুল কারণ এটি শুধুমাত্র লাইন ফিডস রিটার্ন করে, ক্যারিয়েজ রিটার্ন লাইন ফিডস (CRLF) এ বাধা দেয় যা উইন্ডো ইউজ করে।
শুরুতে আপনি টার্গেট ডিরেক্টরিতে পরিবর্তন করবেন এবং প্রতিটি সাবডিরেক্টরি আইডেন্টিফাই করবেন,যার প্রতিটিই হলো সেই স্ন্যাপশট যা আপনি কমিট হিসেবে ইম্পোর্ট করতে চান। আপনি প্রতিটি সাবডিরেক্টরি তে চেঞ্জ করবেন এবং তা এক্সপোর্ট করতে প্রয়োজনীয় কমান্ড গুলো প্রিন্ট করবেন। আপনার ব্যাসিক মেইন লুপটি দেখতে এরকম হবেঃ
last_mark = nil
# loop through the directories
Dir.chdir(ARGV[0]) do
Dir.glob("*").each do |dir|
next if File.file?(dir)
# move into the target directory
Dir.chdir(dir) do
last_mark = print_export(dir, last_mark)
end
end
end
এখানে আপনি প্রতিটি ডিরেক্টরি তে print_export রান করছেন,যা পূর্ববর্তী স্ন্যাপশট এর নির্দেশক এবং মার্ক নিয়ে নেয় এবং তা বর্তমান স্ন্যাপশট এ রিটার্ন করে, যার জন্য এদের মধ্যে ঠিকঠাক ভাবে লিংক তৈরি হয়। মার্ক হচ্ছে একটি আইডেন্টিফায়ারের fast-import টার্ম যা একটি কমিট ক্রিয়েট এর সাথে সাথেই পাঠানো হয়। অর্থাৎ প্রতিটি কমিট কে একটি করে মার্ক দেয়া হয় যাতে আপনি অন্য কমিট গুলোর সাথে বর্তমান কমিট কে লিঙ্ক করতে পারেন। সুতরাং প্রথমেই print_export মেথড এ ডিরেক্টরির নাম থেকে একটি মার্ক জেনারেট করতে হবে।
mark = convert_dir_to_mark(dir)
এজন্য আপনি ডিরেক্টরি গুলো নিয়ে একটি অ্যারে বানাতে পারেন এবং এই অ্যারের ইনডেক্স ভ্যালুকে মার্ক হিসেবে ব্যবহার করতে পারেন, কারণ মার্ক অবশ্যই একটি ইন্টিজার ভ্যালু হতে হবে। আপনার মেথডটি হবে ঠিক এরকমঃ
$marks = []
def convert_dir_to_mark(dir)
if !$marks.include?(dir)
$marks << dir
end
($marks.index(dir) + 1).to_s
end
এখন যেহেতু আপনার কমিট এর একটি ইন্টিজার রিপ্রেজেন্টেশন আছে, আপনার কমিট এর মেটাডাটার জন্য একটি তারিখের প্রয়োজন। কারণ তারিখটি আপনার ডিরেক্টরির নামের সাথে থাকলে আপনার ডাটা পাঠানোর সময় সুবিধা হবে। আপনার print_export ফাইল এর পরবর্তী লাইনটি হবেঃ
date = convert_dir_to_date(dir)
চলুন দেখি convert_dir_to_date এ কি আছেঃ
def convert_dir_to_date(dir)
if dir == 'current'
return Time.now().to_i
else
dir = dir.gsub('back_', '')
(year, month, day) = dir.split('_')
return Time.local(year, month, day).to_i
end
end
এই convert_dir_to_date প্রতিটি ডিরেক্টরির তারিখের জন্য একটি ইন্টিজার ভ্যালু রিটার্ন করে। সর্বশেষ যে মেটা-ইনফরমেশন টি আপনার দরকার তাহলো প্রতিটি কমিট এর জন্য একটি করে কমিটার ডাটা যা আপনি গ্লোবাল ভ্যারিয়েবল হিসেবে ডিক্লেয়ার করবেনঃ
$author = 'John Doe '
এখন আপনি আপনার ইম্পোর্টারের জন্য কমিট ডাটা গুলো প্রিন্ট করতে প্রস্তুত। ইনিশিয়াল ইনফরমেশন নির্দেশ করে যে, আপনি একটি কমিট অবজেক্ট ডিফাইন করেছেন, অবজেক্টটি কোন ব্রাঞ্চে আছে (এ কাজটি করে আপনার জেনারেট করা মার্ক টি ব্যবহার করে), কমিটার এর ইনফরমেশন এবং কমিট করা ম্যাসেজটি এবং সবশেষে যদি পূর্বের কোনো কমিট থেকে থাকে সেটি। কোডটি দেখতে কিছুটা এরকমঃ
# print the import information
puts 'commit refs/heads/master'
puts 'mark :' + mark
puts "committer #{$author} #{date} -0700"
export_data('imported from ' + dir)
puts 'from :' + last_mark if last_mark
এক্ষেত্রে সহজ উপায় হচ্ছে টাইম জোন (-০৭০০) কে একদম হার্ডকোড করে দেয়া। যদি আপনি অন্য কোনো সিস্টেম থেকে ইম্পোর্ট করে থাকেন তবে আপনাকে অবশ্যই টাইম জোন কে একটি অফসেট হিসেবে স্পেসিফাই করে দিতে হবে। আর কমিট ম্যাসেজটি অবশ্যই একটি স্পেশাল ফরম্যাট মেইনটেইন করবে।
data (size)\n(contents)
এই ফরম্যাট টি ওয়ার্ড ডাটা ( ডাটার সাইজ, একটি নতুন লাইন এবং ফাইনালি ডাটা কন্টেন্ট) কে নির্দেশ করছে। কারণ আপনাকে এই সেইম ফরম্যাটটিই পরবর্তীতে ফাইল কন্টেন্ট এ ব্যবহার করতে হবে এবং সেখানে আপনি একটি সাহায্যকারী মেথড ক্রিয়েট করবেন।
export_data:
def export_data(string)
print "data #{string.size}\n#{string}"
end
বাকি থাকলো প্রতিটি স্ন্যাপশট এর জন্য ফাইল কন্টেন্ট স্পেসিফাই করে দেয়া। এটা খুবই সহজ কাজ, কারণ আপনার প্রতিটি ফাইল এইটি ডিরেক্টরি তে আছে। তাই আপনি চাইলেই deleteall কমান্ডটি (ডিরেক্টরির প্রতিটি ফাইলের কন্টেন্ট কে নির্দেশ করে) প্রিন্ট আউট করে দিতে পারেন। এরপর দেখবেন গিট প্রতিটি স্ন্যাপশট ঠিকটঠাকভাবে রেকর্ড করছে।
puts 'deleteall'
Dir.glob("**/*").each do |file|
next if !File.file?(file)
inline_data(file)
end
নোটঃ কারণ অনেক সিস্টেম তাদের পুনরায় ভিজিট করাটাকেই একটি কমিট থেকে অন্যটির চেঞ্জ হিসেবে মনে করে। fast-import কমান্ডের মাধ্যমে বুঝতে পারে প্রতিটি কমিট এ কোন ফাইলগুলো এড করা হয়েছে, মুছে ফেলা হয়েছে অথবা পরিবর্তন করা হয়েছে এবং কোনগুলো নতুন কন্টেন্ট। আপনি স্নাপশট গুলোর মধ্যে পরিবর্তনগুলি ক্যালকুলেট করেও এই ডাটাগুলো পেতে পারতেন কিন্তু সেটা খুবই কঠিন হতো। আপনি চাইলে গিট এ সব ডাটা দিয়ে গিট এর উপরেও এই দায়িত্ব ছেড়ে দিতে পারেন এসব ডাটা খুঁজে বের করার জন্য।
যদি এটা আপনার ডাটার জন্য উপযোগী হয়, তাহলে আপনার ডাটা এই উপায়ে কিভাবে প্রোভাইড করতে হবে এটার ডিটেইলস দেখতে fast-import এর মেইন পেইজ চেক করুন।
নতুন ফাইল কন্টেন্ট এর লিস্ট করতে অথবা নতুন কন্টেন্ট সম্বলিত একটি পরিবর্তিত ফাইল কে স্পেসিফাই করতে ফরম্যাটটি হচ্ছেঃ
M 644 inline path/to/file
data (size)
(file contents)
এখানে ৬৪৪ হচ্ছে মোড (যদি আপনার কাছে এক্সিকিউটেবল ফাইল থাকে, আপনাকে সেটা ডিটেক্ট করে ৬৪৪ এর পরিবর্তে ৭৫৫কে স্পেসিফাই করে দিতে হবে) এবং ইনলাইন দিয়ে বুঝায় আপনি এই লাইনের পরপর ই কন্টেন্ট গুলোর লিস্ট করবেন। আপনার inline_data মেথডটি হবে এরকমঃ
def inline_data(file, code = 'M', mode = '644')
content = File.read(file)
puts "#{code} #{mode} inline #{file}"
export_data(content)
end
আপনি আগে থেকে ডিফাইন করা export_data মেথড কে পুনরায় ব্যবহার করবেন, কারণ এটা করা আর আপনার কমিট ম্যাসেজ ডাটা স্পেসিফাই করার পদ্ধতি একই।
এখন আপনার সর্বশেষ কাজটি হচ্ছে বর্তমান মার্কটিকে রিটার্ন করে দেয়া যাতে এটি পরবর্তী ইটারেশনে পাস হতে পারে।
return mark
নোটঃ
যদি আপনি ইউন্ডোজ ব্যবহার করে থাকেন তাহলে আপনাকে শিউর হতে হবে যে আপনি একটা এক্সট্রা স্টেপ নিয়েছেন। আগেই উল্লেখ করেছি যে ইউন্ডোজ নিউ লাইনের জন্যে CRLF ব্যবহার করে, যেখানে গিট fast-import LF এস্পেক্ট করে। আপনাকে রুবিকে CRLF এর পরিবর্তে LF ব্যবহার করতে বলতে হবে।
$stdout.binmode
ব্যাস, এখানেই শেষ। তাহলে আপনার পুরো স্ক্রিপ্ট টা যেটা দাঁড়ালো তা হলোঃ
#!/usr/bin/env ruby
$stdout.binmode
$author = "John Doe "
$marks = []
def convert_dir_to_mark(dir)
if !$marks.include?(dir)
$marks << dir
end
($marks.index(dir)+1).to_s
end
def convert_dir_to_date(dir)
if dir == 'current'
return Time.now().to_i
else
dir = dir.gsub('back_', '')
(year, month, day) = dir.split('_')
return Time.local(year, month, day).to_i
end
end
def export_data(string)
print "data #{string.size}\n#{string}"
end
def inline_data(file, code='M', mode='644')
content = File.read(file)
puts "#{code} #{mode} inline #{file}"
export_data(content)
end
def print_export(dir, last_mark)
date = convert_dir_to_date(dir)
mark = convert_dir_to_mark(dir)
puts 'commit refs/heads/master'
puts "mark :#{mark}"
puts "committer #{$author} #{date} -0700"
export_data("imported from #{dir}")
puts "from :#{last_mark}" if last_mark
puts 'deleteall'
Dir.glob("**/*").each do |file|
next if !File.file?(file)
inline_data(file)
end
mark
end
# Loop through the directories
last_mark = nil
Dir.chdir(ARGV[0]) do
Dir.glob("*").each do |dir|
next if File.file?(dir)
# move into the target directory
Dir.chdir(dir) do
last_mark = print_export(dir, last_mark)
end
end
end
যদি এই স্ক্রিপ্টটি আপনি রান করেন, আপনার কন্টেন্ট টি দেখতে এরকম হবেঃ
$ ruby import.rb /opt/import_from
commit refs/heads/master
mark :1
committer John Doe 1388649600 -0700
data 29
imported from back_2014_01_02deleteall
M 644 inline README.md
data 28
# Hello
This is my readme.
commit refs/heads/master
mark :2
committer John Doe 1388822400 -0700
data 29
imported from back_2014_01_04from :1
deleteall
M 644 inline main.rb
data 34
#!/bin/env ruby
puts "Hey there"
M 644 inline README.md
(...)
এখন ইম্পোর্টারটিকে রান করতে,এই আউটপুট কে পাইপলাইনের মাধ্যমে গিট fast-import এ পাঠান যেই গিট ডিরেক্টরি তে আপনি ইম্পোর্ট করতে চাচ্ছেন। আপনি চাইলে একটি নতুন ডিরেক্টরি ক্রিয়েট করে তারপর এর স্টার্টিং পয়েন্ট এর জন্য git init রান করতে পারেন। এরপর আপনি আপনার স্ক্রিপ্ট টি রান করবেন।
$ git init
Initialized empty Git repository in /opt/import_to/.git/
$ ruby import.rb /opt/import_from | git fast-import
git-fast-import statistics:
---------------------------------------------------------------------
Alloc'd objects: 5000
Total objects: 13 ( 6 duplicates )
blobs : 5 ( 4 duplicates 3 deltas of 5 attempts)
trees : 4 ( 1 duplicates 0 deltas of 4 attempts)
commits: 4 ( 1 duplicates 0 deltas of 0 attempts)
tags : 0 ( 0 duplicates 0 deltas of 0 attempts)
Total branches: 1 ( 1 loads )
marks: 1024 ( 5 unique )
atoms: 2
Memory total: 2344 KiB
pools: 2110 KiB
objects: 234 KiB
---------------------------------------------------------------------
pack_report: getpagesize() = 4096
pack_report: core.packedGitWindowSize = 1073741824
pack_report: core.packedGitLimit = 8589934592
pack_report: pack_used_ctr = 10
pack_report: pack_mmap_calls = 5
pack_report: pack_open_windows = 2 / 2
pack_report: pack_mapped = 1457 / 1457
---------------------------------------------------------------------
দেখতেই পাচ্ছেন, যখন এটি সফলভাবে সম্পূর্ণ হয়, এটি কি কি কাজ সম্পন্ন করলো সে সংক্রান্ত কিছু স্ট্যাটিসটিক্স আপনাকে দিচ্ছে। এই ক্ষেত্রে আপনি ১৩ টি অবজেক্ট কে টোটাল ৪টি কমিট এর মাধ্যমে একটি ব্রাঞ্চ এ ইম্পোর্ট করেছেন। এখন আপনি git log রান করে আপনার নতুন হিস্টোরি টি দেখতে পাবেন।
$ git log -2
commit 3caa046d4aac682a55867132ccdfbe0d3fdee498
Author: John Doe
Date: Tue Jul 29 19:39:04 2014 -0700
imported from current
commit 4afc2b945d0d3c8cd00556fbe2e8224569dc9def
Author: John Doe
Date: Mon Feb 3 01:00:00 2014 -0700
imported from back_2014_02_03
ফাইনালি,রেডি হয়ে গেলো একটি সুন্দর এবং ক্লিন গিট রিপোজিটরি। এটা খুবই জরুরি খেয়াল রাখা যাতে কোনো স্টেপ বাদ না পড়ে এবং শুরুতেই যাতে আপনার ওয়ার্কিং ডিরেক্টরি তে কোনো ফাইল না থাকে। যদি থেকে থাকে সেক্ষেত্রে আপনার ব্রাঞ্চ কে রিসেট করে নিতে হবে যেখানে বর্তমানে মাস্টার আছে।
$ ls
$ git reset --hard master
HEAD is now at 3caa046 imported from current
$ ls
README.md main.rb
আপনি এই fast-import টুলটি কাজে লাগিয়ে আরো অনেক কিছুই করতে পারবেন – ডিফারেন্ট মোড হ্যান্ডেল করা, বাইনারি ডাটা, মাল্টিপল ব্রাঞ্চ এবং তাদের একত্রিত করা (মার্জিং), প্রগ্রেস ইন্ডিকেটর হিসেবে ব্যবহার করা, এবং আরো অনেক কিছু। আরো কমপ্লেক্স সিচুয়েশন সম্বলিত উদাহরণ দেখতে চাইলে গিট সোর্স কোড এর contrib/fast-import ডিরেক্টরিতে পাবেন।