Menu
২.২ গিট বেসিক – রিপোজিটরিতে পরিবর্তন সংরক্ষন করা
রিপোজিটরিতে পরিবর্তন সংরক্ষণ
এখন আমাদের কাছে একটি সক্রিয় গিট রিপোজিটরি আছে এবং একটি চেকআউট বা ওয়ার্কিং কপি আছে। স্বাভাবিকভাবে আপনি এখন ফাইল গুলো পরিবর্তন করতে চাইবেন এবং প্রায়ই আপনি পরিবর্তনগুলোর স্ন্যাপশট রিপোজিটরিতে সংরক্ষণ বা কমিট করতে চাইবেন। এখানে আমাদের মনে রাখতে হবে যে আমাদের ওয়ার্কিং ডিরেক্টরির ফাইলগুলো দু’টি অবস্থায় থাকতে পারে: ট্র্যাকড অথবা আনট্র্যাকড। ট্র্যাকড ফাইলগুলো হল এমন ফাইল যা সর্বশেষ স্ন্যাপশট বা কমিটে ছিল অথবা যেকোন নতুন স্টেজড ফাইল যা অপরিবর্তিত বা পরিবর্তিত উভয়ই হতে পারে । সহজ কথায়, যে ফাইলগুলোর ব্যাপারে গিট জানে। আর বাকিসব ফাইল হলো আনট্র্যাকড ফাইল, যেমন: ওয়ার্কিং ডিরেক্টরির এমন ফাইল যা এর আগের স্ন্যাপশট বা কমিটে ছিল না এবং স্টেজড অবস্থায়ও নেই। যখন কোন রিপোজিটরি প্রথমবার ক্লোন করা হয়, তখন ওই ডিরেক্টরির সব ফাইল ট্র্যাকড এবং অপরিবর্তিত থাকে। কারণ কোনো ফাইল তখনো পরিবর্তন করা হয়নি। যখন কোনো ফাইল পরিবর্তন করা হবে গিট তাকে পরিবর্তিত অবস্থায় দেখবে, কারণ ফাইলগুলো সর্বশেষ কমিট এর পর পরিবর্তন করা হয়েছে। এরপর বাছাই করা পরিবর্তিত ফাইলগুলোকে স্টেইজ করে তারপর কমিট করা হবে।![](https://staging.vivasoftltd.com/wp-content/uploads/2023/02/lifecycle.png)
ফাইলের স্ট্যাটাস নির্ধারণ
যে কমান্ড দিয়ে কোনো ফাইল এখন কোন অবস্থায় আছে তা দেখা যায় সেটা হল git status। একটি রিপোজিটরি ক্লোন করার পর যদি কমান্ডটি চালানো হয় তাহলে টার্মিনালে এই আউটপুট দেখা যাবে:
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean
এর মানে আপনার ওয়ার্কিং ডিরেক্টরি এই মুহুর্তে ক্লিন, অর্থাৎ এই রিপোজিটরির কোনো ট্র্যাকড ফাইল পরিবর্তিত হয়নি। এর পাশাপাশি গিট কোনো আনট্র্যাকড ফাইল এই ডিরেক্টরিতে খুঁজে পায়নি, পেলে তা উপরের আউটপুটে উল্লেখ থাকতো। সবশেষে, এই কমান্ড আপনাকে জানাচ্ছে আপনি কোন ব্রাঞ্চে আছেন এবং আপনার ব্রাঞ্চ, সার্ভারের একই ব্রাঞ্চ থেকে বিচ্যুত হয়নি। আপাতত ব্রাঞ্চটি masterথাকবে, যা গিট এর ডিফল্ট ব্রাঞ্চ; ব্রাঞ্চের ব্যাপারে আপাতত আমাদের মাথা না ঘামালেও চলবে। গিট ব্র্যাঞ্চিং এ ব্র্যাঞ্চিং সম্পর্কে বিস্তারিত আলোচনা করা হবে।
নোট: ২০২০ সালের মাঝামাঝিতে গিটহাব ডিফল্ট ব্রাঞ্চের নাম master থেকে পরিবর্তন করে main রাখে এবং অন্যান্য গিট হোস্টরাও পরবর্তীতে main ব্রাঞ্চকে ডিফল্ট ব্রাঞ্চ হিসেবে ব্যবহার শুরু করে। তাই এখন অনেক নতুন রিপোজিটরিতে ডিফল্ট ব্রাঞ্চ হিসেবে main ব্রাঞ্চ দেখা যায়। এছাড়াও ডিফল্ট ব্রাঞ্চ এর নাম প্রয়োজনমত পরিবর্তন করা যায়, তাই আপনি অনেক রিপোজিটরির ডিফল্ট ব্রাঞ্চ এর নাম ভিন্ন দেখতে পারেন। অবশ্য গিট নিজে ডিফল্ট ব্রাঞ্চ এর নাম হিসেবে এখনো master ব্যবহার করে, তাই আমরা এই বইয়ে এই নামই ব্যবহার করবো।
ধরা যাক আপনি আপনার প্রজেক্টে একটি নতুন ফাইল নিয়ে আসলেন, যেমন একটি README ফাইল। যদি ফাইলটি আগে আপনার প্রজেক্টে না থেকে থাকে এবং আপনি যদি এখন git status কমান্ডটি রান করান তাহলে আপনি আপনার আনট্র্যাকড ফাইলটি টার্মিনালের আউটপুটে এভাবে দেখতে পাবেন:
নোট: ২০২০ সালের মাঝামাঝিতে গিটহাব ডিফল্ট ব্রাঞ্চের নাম master থেকে পরিবর্তন করে main রাখে এবং অন্যান্য গিট হোস্টরাও পরবর্তীতে main ব্রাঞ্চকে ডিফল্ট ব্রাঞ্চ হিসেবে ব্যবহার শুরু করে। তাই এখন অনেক নতুন রিপোজিটরিতে ডিফল্ট ব্রাঞ্চ হিসেবে main ব্রাঞ্চ দেখা যায়। এছাড়াও ডিফল্ট ব্রাঞ্চ এর নাম প্রয়োজনমত পরিবর্তন করা যায়, তাই আপনি অনেক রিপোজিটরির ডিফল্ট ব্রাঞ্চ এর নাম ভিন্ন দেখতে পারেন। অবশ্য গিট নিজে ডিফল্ট ব্রাঞ্চ এর নাম হিসেবে এখনো master ব্যবহার করে, তাই আমরা এই বইয়ে এই নামই ব্যবহার করবো।
ধরা যাক আপনি আপনার প্রজেক্টে একটি নতুন ফাইল নিয়ে আসলেন, যেমন একটি README ফাইল। যদি ফাইলটি আগে আপনার প্রজেক্টে না থেকে থাকে এবং আপনি যদি এখন git status কমান্ডটি রান করান তাহলে আপনি আপনার আনট্র্যাকড ফাইলটি টার্মিনালের আউটপুটে এভাবে দেখতে পাবেন:
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean
$ echo 'My Project' > README
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
(use "git add ..." to include in what will be committed)
README
nothing added to commit but untracked files present (use "git add" to track)
এখানে আপনার README ফাইলটি আনট্র্যাকড অবস্থায় আছে, কারণ এটি স্ট্যাটাস আউটপুটের আনট্র্যাকড ফাইল অংশে দেখাচ্ছে। আনট্র্যাকড বলতে বোঝায় গিটের কাছে ফাইলটির তথ্য, আগের স্ন্যাপশট বা কমিটে ছিল না এবং যেটি এখনো স্টেইজ করা হয়নি। গিট ততক্ষন পর্যন্ত এই ফাইলটি আপনার কমিট স্ন্যাপশটে অন্তর্ভুক্ত করবে না, যতক্ষণ না আপনি গিটকে স্পষ্ট করে সেই নির্দেশ দিবেন। এর মাধ্যমে গিট নিশ্চিত করে যে আপনি ভুলক্রমে কোনো অনাকাঙ্ক্ষিত ফাইল যেন অন্তর্ভুক্ত না হয়ে যায়। এখন আমরা README ফাইলটি স্নাপশটে অন্তর্ভুক্ত করার জন্য ফাইলটি ট্র্যাক করা শুরু করতে পারি।
নতুন ফাইল ট্র্যাক করা
নতুন ফাইল ট্র্যাক করার জন্য git add কমান্ড ব্যবহার করা হয়। README ফাইলটি ট্র্যাক করতে কমান্ডটি চালাই:
$ git add README
এখন যদি git status কমান্ডটি চালানো হয় তাহলে দেখতে পাবেন যে README ফাইলটি এখন ট্র্যাক করা হচ্ছে এবং কমিট এর জন্য স্টেজড অবস্থায় আছে।
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git restore --staged ..." to unstage)
new file: README
ফাইলটি আউটপুটের চেঞ্জেস টু বি কমিটেড অংশে দেখাচ্ছে, অর্থাৎ ফাইলটি এখন স্টেজড অবস্থায় আছে। এখন এই পর্যায়ে যদি কমিট করা হয়, তাহলে ফাইলের যে ভার্সনটি git add কমান্ড চালানোর সময় ছিল, সেটি পরের স্ন্যাপশট বা কমিটে অন্তর্ভুক্ত হবে। এর আগে যখন git init কমান্ডটি এবং তারপর git add কমান্ডটি চালানো হয়েছিলো, তখনই ডিরেক্টরির ফাইলগুলো ট্র্যাক হওয়া শুরু করে। git add কমান্ডটি আর্গুমেন্ট হিসেবে একটি পাথ-নেইম নেয়। এই পাথটি হতে পারে একটি ফাইলের অথবা একটি ডিরেক্টরির। যদি এটি ডিরেক্টরি হয় তাহলে কমান্ডটি বারেবারে বা রিকার্সিভলি ডিরেক্টরির সকল ফাইল স্টেইজে অন্তর্ভুক্ত করে।
পরিবর্তিত ফাইল স্টেজ করা
এবার এমন একটি ফাইল পরিবর্তন করা যাক যা এখন ট্র্যাক হচ্ছে। আমরা যদি CONTRIBUTING.md নামের ফাইলটি, যেটা আগে থেকে ট্র্যাক হচ্ছে, পরিবর্তন করি এবং git status কমান্ডটি চালাই তাহলে টার্মিনালে আউটপুট এমন দেখাবে:
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD ..." to unstage)
new file: README
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: CONTRIBUTING.md
এখানে CONTRIBUTING.md ফাইলটি চেঞ্জেস টু বি কমিটেড অংশে দেখাচ্ছে, অর্থ্যাৎ ওয়ার্কিং ডিরেক্টরিতে একটি ফাইল ট্র্যাক করা হচ্ছিলো, যেটা পরিবর্তন করা হয়েছে কিন্তু পরিবর্তনটি স্টেইজ করা হয়নি। স্টেইজ করার জন্য আপনাকে git add কমান্ডটি চালাতে হবে। git add কমান্ডটি একটি বহুমুখী কমান্ড হিসেবে ব্যবহৃত হয় – এই কমান্ড ব্যবহার করে ফাইল ট্র্যাক করা, ফাইল স্টেইজ করা এবং আরো কাজ যেমন মার্জ কনফ্লিক্টেড ফাইলগুলো রিসল্ভড হিসেবে চিহ্নিত করা ইত্যাদি করা যায়। এটাকে আমরা “এই ফাইলটি প্রজেক্টে যুক্ত করা”- এভাবে চিন্তা করার চাইতে “পরবর্তী কমিটে এই নির্দিষ্ট কনটেন্টটি যুক্ত করা”- এভাবে চিন্তা করতে পারি। এখন আমরা git add চালিয়ে CONTRIBUTING.md ফাইলটি স্টেইজ করি, তারপর এই ডিরেক্টরির বর্তমান অবস্থা জানতে git status কমান্ডটি চালাই:
$ git add CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD ..." to unstage)
new file: README
modified: CONTRIBUTING.md
এখন দুইটি ফাইলই স্টেইজড অবস্থায় আছে পরবর্তী কমিটে অন্তর্ভুক্ত হওয়ার জন্য। এখন আপনার মনে হলো কমিট করার আগে CONTRIBUTING.md ফাইলে আরো কিছু পরিবর্তন করা প্রয়োজন। আপনি ফাইলটি আবার পরিবর্তন করলেন এবং এখন আপনি কমিট করতে চান। এখন আপনি আবার একবার git status কমান্ডটি রান করলেন:
$ vim CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD ..." to unstage)
new file: README
modified: CONTRIBUTING.md
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: CONTRIBUTING.md
কিন্ত এ কি? CONTRIBUTING.md ফাইল স্টেইজড এবং আনস্টেজড দুই অবস্থাতেই আছে! কিন্তু তা কিভাবে সম্ভব? আসলে এখানে যা হয়, যখন git add কমান্ড চালানো হয় ফাইলটি যেভাবে আছে গিট সেটাকে ঠিক সেভাবেই স্টেইজ করে। এখন এই অবস্থায় যদি কমিট করা হয়, তাহলে সর্বশেষ যখন git add রান করা হয় তখন CONTRIBUTING.md যে অবস্থায় স্টেইজ হয়েছিল ঠিক সেই অবস্থায় কমিট হবে, পরের পরিবর্তনটি এই কমিট এ অন্তর্ভুক্ত হবে না। যদি স্টেইজ করার পর স্টেইজ করা ফাইলটি পরিবর্তন করা হয় তাহলে আবার git add রান করে ফাইলটির সর্বশেষ ভার্সন স্টেইজ করতে হবে:
$ git add CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD ..." to unstage)
new file: README
modified: CONTRIBUTING.md
সংক্ষিপ্ত স্ট্যাটাস
যদিও git status এর আউটপুট যথেষ্ট বোধগম্য, কিন্তু তা বেশ বড়। তাই গিট স্ট্যাটাস এর একটি সংক্ষিপ্ত ফ্ল্যাগ (flag) আছে। এর আউটপুট বেশ সংক্ষেপে এবং সহজভাবে ডিরেক্টরির বর্তমান অবস্থা বর্ণনা করে। আপনি যদি git status -s অথবা git status –short কমান্ড রান করেন তাহলে এই আউটপুট পাবেন:
$ git status -s
M README
MM Rakefile
A lib/git.rb
M lib/simplegit.rb
?? LICENSE.txt
এই কমান্ডের আউটপুটে যে নতুন ফাইলগুলো ট্র্যাক করা হচ্ছে না সেগুলোর পাশে “??” চিহ্ন, যেগুলো স্টেইজিং এর জন্য এড করা হয়েছে তাদের পাশে “A” এবং পরিবর্তিত ফাইলের পাশে “M” নির্দেশক থাকে। এখানে প্রতিটি ফাইল এর দুইটি কলাম থাকে – বামপাশের কলাম স্টেজিং এরিয়ার অবস্থা নির্দেশ করে এবং ডানপাশের কলাম ওয়ার্কিং ট্রি এর অবস্থা নির্দেশ করে। আমরা উপরের আউটপুট থেকে দেখতে পাই যে, README ফাইল পরিবর্তিত হয়েছে কিন্তু স্টেইজ করা হয় নি, lib/simplegit.rb পরিবর্তন করার পরে স্টেইজ করা হয়েছে। আর Rakefile পরিবর্তন করে স্টেইজ করার পর আবার পরিবর্তন করা হয়েছে, তাই এই ফাইলটি স্টেজড এবং আনস্টেজড দুই অবস্থাতেই আছে।
ফাইল ইগনোর করা
প্রায়ই আপনার কাছে এমন কিছু ধরণের ফাইল থাকবে যা আপনি চান না সেগুলো গিট স্বয়ংক্রিয়ভাবে যোগ করুক বা এমনকি ফাইলগুলি আনট্র্যাকড অবস্থায় আছে বলেও দেখাক। এগুলি সাধারণত লগ ফাইল বা বিল্ড সিস্টেম দিয়ে স্বয়ংক্রিয়ভাবে তৈরি করা ফাইল। এক্ষেত্রে আপনি .gitignore নামে একটি ফাইল তৈরী করে তার মধ্যে প্যাটার্নগুলির একটি তালিকা করতে পারেন। এখানে উদাহরণস্বরূপ একটি .gitignore ফাইল দেয়া হল:
$ cat .gitignore
*.[oa]
*~
প্রথম লাইনটি গিটকে যেসব ফাইলের শেষে “.o” বা “.a” আছে — অর্থাৎ অবজেক্ট এবং আর্কাইভ ফাইলগুলিকে ইগনোর করতে বলে যেগুলো আপনার কোড বিল্ডের সময় তৈরী হতে পারে। দ্বিতীয় লাইনটি গিটকে টিল্ড (~) দিয়ে শেষ হওয়া সব ফাইলকে ইগনোর (ignore) করতে বলে। অস্থায়ী ফাইল মার্ক করার জন্য অনেক টেক্সট এডিটর, যেমন Emacs টিল্ড (~) ব্যবহার করে। আপনি একটি log, tmp, pid ডিরেক্টরি; স্বয়ংক্রিয়ভাবে তৈরি ডকুমেন্টেশন এবং আরো অনেক কিছু .gitignore ফাইলে অন্তর্ভুক্ত করতে পারেন। কাজ শুরু করার আগেই আপনার নতুন রিপোজিটোরির জন্য একটি .gitignore ফাইল সেট আপ করা উচিৎ, কারণ তাতে আপনি চান না এমন কোনো ফাইল ভুলবশত গিট রিপোজিটোরিতে কমিট হবে না।
.gitignore ফাইলে যে প্যাটার্নগুলি রাখতে পারেন তার উদাহরণ:
- # দিয়ে শুরু হওয়া লাইন অথবা ফাঁকা লাইনগুলি ইগনোর করা।
- স্ট্যান্ডার্ড গ্লোব প্যাটার্নগুলি ব্যবহার করা যাবে এবং তা পুরো ওয়ার্কিং ট্রি তে রিকার্সিভলি কাজ করবে।
- আপনি পুনরাবৃত্তি\এড়াতে একটি ফরোয়ার্ড স্ল্যাশ (/) দিয়ে প্যাটার্নগুলি শুরু করতে পারেন।
- আপনি একটি ডিরেক্টরি নির্দিষ্ট করতে একটি ফরোয়ার্ড স্ল্যাশ (/) দিয়ে প্যাটার্ন শেষ করতে পারেন।
- আপনি একটি বিস্ময়সূচক চিহ্ন (!) দিয়ে শুরু করে একটি প্যাটার্নকে বাদ দিতে পারেন।
গ্লোব প্যাটার্নগুলি সহজ রেগুলার এক্সপ্রেশনের মতো যা শেল ব্যবহার করে। একটি এস্টেরিক(*) শূন্য বা তার বেশি অক্ষরের সাথে মেলে; [abc] বন্ধনীর ভিতরের যেকোনো একটি অক্ষরের সাথে মেলে (এই ক্ষেত্রে a, b, বা c); একটি প্রশ্ন চিহ্ন (?) একটি একক অক্ষরের সাথে মেলে; এবং হাইফেন ([0-9]) দিয়ে বিভক্ত অক্ষরগুলিকে তাদের মধ্যে যেকোনো অক্ষরের সাথে মেলে (এই ক্ষেত্রে 0 থেকে 9)। এছাড়াও আপনি নেস্টেড ডিরেক্টরিগুলি মেলানোর জন্য দুটি এস্টেরিক ব্যবহার করতে পারেন; যেমন a/**/z দিয়ে মিলবে a/z, a/b/z, a/b/c/z, ইত্যাদি।
এখানে আরেকটি .gitignore ফাইলের উদাহরণ দেয়া হল:
# ignore all .a files
*.a
# but do track lib.a, even though you're ignoring .a files above
!lib.a
# only ignore the TODO file in the current directory, not subdir/TODO
/TODO
# ignore all files in any directory named build
build/
# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt
# ignore all .pdf files in the doc/ directory and any of its subdirectories
doc/**/*.pdf
টিপ: প্রজেক্ট শুরু করার জন্য গিটহাবে (https://github.com/github/gitignore) কয়েক ডজন প্রজেক্ট ও ভাষার জন্য .gitignore ফাইলের উদাহরণ দিয়ে মোটামুটি বিশাল একটা সংগ্রহ আছে।
নোট: সাধারণ ক্ষেত্রে, একটি রিপোজিটরির রুট ডিরেক্টরিতে একটি মাত্র .gitignore ফাইল থাকতে পারে, যা পুরো রিপোজিটরিতে রিকার্সিভলি প্রযোজ্য হয়। যাইহোক, সাবডিরেক্টরিগুলোতে অতিরিক্ত .gitignore ফাইল থাকাও সম্ভব। এই নেস্টেড .gitignore ফাইলগুলির নিয়মগুলি শুধুমাত্র সেই সাবডিরেক্টরির ফাইলগুলির জন্য প্রযোজ্য। লিনাক্স কার্নেল সোর্স রিপোজিটরিতে ২০৬টি .gitignore ফাইল রয়েছে। একাধিক gitignore ফাইল নিয়ে বিস্তারিত এই বইয়ের আলোচ্য বিষয় নয়। বিস্তারিত জানার জন্য man gitignore দেখুন।
নোট: সাধারণ ক্ষেত্রে, একটি রিপোজিটরির রুট ডিরেক্টরিতে একটি মাত্র .gitignore ফাইল থাকতে পারে, যা পুরো রিপোজিটরিতে রিকার্সিভলি প্রযোজ্য হয়। যাইহোক, সাবডিরেক্টরিগুলোতে অতিরিক্ত .gitignore ফাইল থাকাও সম্ভব। এই নেস্টেড .gitignore ফাইলগুলির নিয়মগুলি শুধুমাত্র সেই সাবডিরেক্টরির ফাইলগুলির জন্য প্রযোজ্য। লিনাক্স কার্নেল সোর্স রিপোজিটরিতে ২০৬টি .gitignore ফাইল রয়েছে। একাধিক gitignore ফাইল নিয়ে বিস্তারিত এই বইয়ের আলোচ্য বিষয় নয়। বিস্তারিত জানার জন্য man gitignore দেখুন।
স্টেজড এবং আনস্টেজেড পরিবর্তন দেখা
যদি git status কমান্ডের দেয়া তথ্যগুলো আপনার জন্য যথেষ্ট না হয় — আপনি শুধু কোন ফাইলগুলি পরিবর্তন করা হয়েছে তা না জানতে চান, ফাইলগুলোতে ঠিক কী পরিবর্তন করেছেন তাও জানতে চান — তাহলে git diff কমান্ডটি ব্যবহার করতে পারেন। আমরা পরে আরও বিস্তারিত git diff নিয়ে আলোচনা করব, তবে আপনি সম্ভবত এই দুটি প্রশ্নের উত্তর দেওয়ার জন্য এটি প্রায়ই ব্যবহার করবেন: আপনি কী পরিবর্তন করেছেন কিন্তু এখনও স্টেজড করেননি? এবং আপনি কি স্টেজ করেছেন যা আপনি এখন কমিট করতে যাচ্ছিলেন? যদিও git status ফাইলের নামগুলি লিস্ট করে এই প্রশ্নগুলির উত্তর দেয়, তবে git diff আপনাকে কোন কোন লাইন পরিবর্তন অথবা সরানো হয়েছিল তা দেখায় এবং তার সাথে প্যাচ দেখায়, যেমনটি আগে ছিল। ধরা যাক, আপনি README ফাইলটিকে আবার পরিবর্তন এবং স্টেজ করেছেন এবং তারপর CONTRIBUTING.md ফাইলটি স্টেজ না করেই পরিবর্তন করেছেন। এখন আপনি যদি আপনার গিট স্ট্যাটাস git status কমান্ডটি চালান তবে আপনি আবার এরকম কিছু দেখতে পাবেন:
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD ..." to unstage)
modified: README
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: CONTRIBUTING.md
আপনি কি পরিবর্তন করেছেন কিন্তু এখনও স্টেজ করেননি যদি তা দেখতে চান, তাহলে অন্য কোন আর্গুমেন্ট ছাড়া git diff টাইপ করুন:
$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
Please include a nice description of your changes when you submit your PR;
if we have to read the whole diff to figure out why you're contributing
in the first place, you're less likely to get feedback and have your change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if your patch is
+longer than a dozen lines.
If you are starting to work on a particular area, feel free to submit a PR
that highlights your work in progress (and note in the PR title that it's
এই কমান্ডটি আপনার স্টেজিং এরিয়াতে যা আছে, তার সাথে আপনার ওয়ার্কিং ডিরেক্টরিতে যা আছে তার তুলনা করে। তাহলে আপনি যে পরিবর্তনগুলি করেছেন কিন্তু এখনও কমিটি করেননি তা আউটপুটে দেখাবে।
যদি দেখতে চান যে আপনি কী স্টেজ করেছেন যা পরবর্তী কমিট-এ যাবে, তাহলে git diff –staged ব্যবহার করতে পারেন। এই কমান্ডটি আপনার স্টেজড পরিবর্তনগুলিকে আপনার শেষ কমিটের সাথে তুলনা করে:
যদি দেখতে চান যে আপনি কী স্টেজ করেছেন যা পরবর্তী কমিট-এ যাবে, তাহলে git diff –staged ব্যবহার করতে পারেন। এই কমান্ডটি আপনার স্টেজড পরিবর্তনগুলিকে আপনার শেষ কমিটের সাথে তুলনা করে:
$ git diff --staged
diff --git a/README b/README
new file mode 100644
index 0000000..03902a1
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+My Project
এটি লক্ষ্য করা গুরুত্বপূর্ণ যে git diff নিজেই আপনার শেষ কমিট থেকে করা সমস্ত পরিবর্তন দেখায় না —- দেখায় শুধুমাত্র পরিবর্তনগুলি যা এখনও স্টেজ করা হয়নি। যদি আপনার সমস্ত পরিবর্তনগুলি কমিট করে থাকেন তবে git diff কোন আউটপুট দেবে না।
আবারো আরেকটি উদাহরণ লক্ষ করি, যদি CONTRIBUTING.md ফাইলটি স্টেজ করেন এবং তারপরে এটি পরিবর্তন করেন, তাহলে আপনি স্টেজ করা ফাইলের পরিবর্তন এবং স্টেজ না করা পরিবর্তনগুলি দেখতে git diff ব্যবহার করতে পারেন। যদি আমাদের ইনভায়রনমেন্ট এইরকম দেখায়:
আবারো আরেকটি উদাহরণ লক্ষ করি, যদি CONTRIBUTING.md ফাইলটি স্টেজ করেন এবং তারপরে এটি পরিবর্তন করেন, তাহলে আপনি স্টেজ করা ফাইলের পরিবর্তন এবং স্টেজ না করা পরিবর্তনগুলি দেখতে git diff ব্যবহার করতে পারেন। যদি আমাদের ইনভায়রনমেন্ট এইরকম দেখায়:
$ git add CONTRIBUTING.md
$ echo '# test line' >> CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD ..." to unstage)
modified: CONTRIBUTING.md
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: CONTRIBUTING.md
তাহলে এখন আপনি যা এখনও স্টেজ করা হয়নি তা দেখতে git diff ব্যবহার করতে পারেন:
$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 643e24f..87f08c8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -119,3 +119,4 @@ at the
## Starter Projects
See our [projects list](https://github.com/libgit2/libgit2/blob/development/PROJECTS.md).
+# test line
এবং git diff –cached ব্যবহার করতে পারেন এখন পর্যন্ত কী স্টেজ করেছেন তা দেখতে (–staged এবং –cached সমার্থক):
$ git diff --cached
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
Please include a nice description of your changes when you submit your PR;
if we have to read the whole diff to figure out why you're contributing
in the first place, you're less likely to get feedback and have your change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if your patch is
+longer than a dozen lines.
If you are starting to work on a particular area, feel free to submit a PR
that highlights your work in progress (and note in the PR title that it's
নোট: একটি বাহ্যিক টুলে git diff
আমরা বইয়ের বাকি অংশ জুড়ে বিভিন্ন উপায়ে git diff কমান্ডটি ব্যবহার করব। আপনি যদি পরিবর্তে একটি গ্রাফিকাল বা এক্সটারনাল diff দেখার প্রোগ্রাম পছন্দ করেন তবে এর জন্য আরেকটি উপায় আছে। আপনি যদি git diff এর পরিবর্তে git difftool চালান, তাহলে আপনি যেকোনো diffs দেখতে পারবেন emerge, vimdiff এবং আরও অনেক কিছু সফটওয়ারে (বাণিজ্যিক পণ্য সহ) । আপনার সিস্টেমে কি এভেইলেবল আছে তা দেখতে git difftool –tool-help চালান।
আমরা বইয়ের বাকি অংশ জুড়ে বিভিন্ন উপায়ে git diff কমান্ডটি ব্যবহার করব। আপনি যদি পরিবর্তে একটি গ্রাফিকাল বা এক্সটারনাল diff দেখার প্রোগ্রাম পছন্দ করেন তবে এর জন্য আরেকটি উপায় আছে। আপনি যদি git diff এর পরিবর্তে git difftool চালান, তাহলে আপনি যেকোনো diffs দেখতে পারবেন emerge, vimdiff এবং আরও অনেক কিছু সফটওয়ারে (বাণিজ্যিক পণ্য সহ) । আপনার সিস্টেমে কি এভেইলেবল আছে তা দেখতে git difftool –tool-help চালান।
আপনার পরিবর্তনগুলো কমিট করা
এখন যেহেতু স্টেজিং এরিয়া আপনি যেভাবে চান সেভাবে সেট আপ করা হয়েছে, আপনি আপনার পরিবর্তনগুলি কমিট করতে পারেন। মনে রাখবেন যা এখনও স্টেজ করা হয়নি — অথবা কোনো ফাইল আপনি তৈরি করেছেন বা পরিবর্তন করেছেন যা পরিবর্তন করার পর থেকে git add রান করেননি — এগুলো কমিট-এ যাবে না। এগুলি আপনার ডিস্কে পরিবর্তিত ফাইল হিসাবে থাকবে। এই ক্ষেত্রে, ধরা যাক যে আপনি শেষবার git status কমান্ডটি চালিয়েছিলেন, আপনি দেখেছিলেন যে সবকিছুই স্টেজড হয়েছে, তাই আপনি আপনার পরিবর্তনগুলি কমিট করতে প্রস্তুত। কমিট করার সবচেয়ে সহজ উপায় হল git commit টাইপ করা:
$ git commit
এটি করার ফলে আপনার পছন্দের ইডিটর চালু হয়।
নোট: এটি আপনার শেলের এডিটর এনভায়রনমেন্ট ভেরিয়েবল সাধারণত ভিম বা ই-ম্যাক্স দিয়ে সেট করা হয়, যদিও আপনি git config –global core.editor কমান্ডটি ব্যবহার করে যা চান তা দিয়ে কনফিগার করতে পারেন যেমন আপনি শুরুতে দেখেছেন।
এডিটর নিচের টেক্সট প্রদর্শন করে (এই উদাহরণটি একটি ভিম স্ক্রিন):
নোট: এটি আপনার শেলের এডিটর এনভায়রনমেন্ট ভেরিয়েবল সাধারণত ভিম বা ই-ম্যাক্স দিয়ে সেট করা হয়, যদিও আপনি git config –global core.editor কমান্ডটি ব্যবহার করে যা চান তা দিয়ে কনফিগার করতে পারেন যেমন আপনি শুরুতে দেখেছেন।
এডিটর নিচের টেক্সট প্রদর্শন করে (এই উদাহরণটি একটি ভিম স্ক্রিন):
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Your branch is up-to-date with 'origin/master'.
#
# Changes to be committed:
# new file: README
# modified: CONTRIBUTING.md
#
~
~
~
".git/COMMIT_EDITMSG" 9L, 283C
আপনি দেখতে পাচ্ছেন যে ডিফল্ট কমিট মেসেজে মন্তব্য করা git status কমান্ডের সর্বশেষ আউটপুট রয়েছে এবং উপরে একটি খালি লাইন রয়েছে। আপনি এই মন্তব্যগুলি মুছে ফেলতে পারেন এবং আপনার কমিট মেসেজ টাইপ করতে পারেন, অথবা আপনি যা কমিট করছেন তা মনে রাখতে সাহায্য করার জন্য আপনি সেগুলি সেখানে রেখে যেতে পারেন।
নোট: আপনি কী পরিবর্তন করেছেন তা আরও স্পষ্ট ভাবে জানার জন্য, আপনি git commit করার সময় -v অপশন হিসেবে যোগ করতে পারেন। এটি করা আপনার পরিবর্তনের পার্থক্যটি এডিটরে রাখে যাতে আপনি ঠিক কী পরিবর্তন করছেন তা দেখতে পারেন।
আপনি যখন এডিটর থেকে বের হয়ে যান, গিট সেই কমিট মেসেজের সাথে আপনার কমিট তৈরি করে (মন্তব্য এবং পার্থক্য বাদ দিয়ে)।
বিকল্পভাবে, আপনি commit কমান্ডের সাথে একটি -m ফ্ল্যাগের পরে নির্দিষ্ট করে আপনার কমিট মেসেজ ইনলাইনে টাইপ করতে পারেন, যেমন:
নোট: আপনি কী পরিবর্তন করেছেন তা আরও স্পষ্ট ভাবে জানার জন্য, আপনি git commit করার সময় -v অপশন হিসেবে যোগ করতে পারেন। এটি করা আপনার পরিবর্তনের পার্থক্যটি এডিটরে রাখে যাতে আপনি ঠিক কী পরিবর্তন করছেন তা দেখতে পারেন।
আপনি যখন এডিটর থেকে বের হয়ে যান, গিট সেই কমিট মেসেজের সাথে আপনার কমিট তৈরি করে (মন্তব্য এবং পার্থক্য বাদ দিয়ে)।
বিকল্পভাবে, আপনি commit কমান্ডের সাথে একটি -m ফ্ল্যাগের পরে নির্দিষ্ট করে আপনার কমিট মেসেজ ইনলাইনে টাইপ করতে পারেন, যেমন:
$ git commit -m "Story 182: fix benchmarks for speed"
[master 463dc4f] Story 182: fix benchmarks for speed
2 files changed, 2 insertions(+)
create mode 100644 README
এখন আপনি আপনার প্রথম কমিট তৈরি করেছেন। আপনি দেখতে পাচ্ছেন যে কমিট আপনাকে নিজের সম্পর্কে কিছু আউটপুট দিয়েছে: আপনি কোন ব্রাঞ্চে কমিট করেছেন (master), কমিটটিতে কী SHA-1 চেকসাম রয়েছে (463dc4f), কতগুলি ফাইল পরিবর্তন করা হয়েছে এবং লাইনগুলিতে যোগ করা এবং সরানো সম্পর্কে পরিসংখ্যান দিয়েছে।
মনে রাখবেন যে কমিট আপনার স্টেজিং এরিয়ায় আপনার সেট আপ করা স্ন্যাপশট রেকর্ড করে। আপনি যা স্ট্যাজ করেননি তা এখনও সেখানে মডিফাইড অবস্থায় রয়েছে; আপনি আপনার হিস্টোরিতে এটি যোগ করার জন্য আরেকটি কমিট করতে পারেন। প্রতিবার আপনি একটি কমিট করার সময়, আপনার প্রজেক্টের একটি স্ন্যাপশট রেকর্ড করছেন যা আপনি পরে ফিরে যেতে বা তুলনা করতে পারেন।
মনে রাখবেন যে কমিট আপনার স্টেজিং এরিয়ায় আপনার সেট আপ করা স্ন্যাপশট রেকর্ড করে। আপনি যা স্ট্যাজ করেননি তা এখনও সেখানে মডিফাইড অবস্থায় রয়েছে; আপনি আপনার হিস্টোরিতে এটি যোগ করার জন্য আরেকটি কমিট করতে পারেন। প্রতিবার আপনি একটি কমিট করার সময়, আপনার প্রজেক্টের একটি স্ন্যাপশট রেকর্ড করছেন যা আপনি পরে ফিরে যেতে বা তুলনা করতে পারেন।
ষ্টেজিং এরিয়া স্কিপ করা
যদিও সম্পূর্ন নিজের মত করে কমিট করতে পারাটা খুবই চমৎকার একটি বিষয়, কিন্তু এর ফলে মাঝে মধ্যে স্টেজিং এরিয়াটি কিছুটা জটিল বা অগোছালো হয়ে যেতে পারে। স্টেজিং এরিয়া স্কিপ করে পরের ধাপে যাওয়ার জন্য গিট্-এর একটি সহজ শর্টকাট রয়েছে। git commit কমান্ড এর সাথে -a অপশনটি যুক্ত করে দিলে গিট্ নিজে থেকেই এই কমিট এর আগ পর্যন্ত থাকা সকল ট্র্যাকড ফাইলকে স্টেইজ করে কমিট করে দেয়, ফলে git add কমান্ড টি আর ব্যবহার করার প্রয়োজন হয়না :
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: CONTRIBUTING.md
no changes added to commit (use "git add" and/or "git commit -a")
$ git commit -a -m 'Add new benchmarks'
[master 83e38c7] Add new benchmarks
1 file changed, 5 insertions(+), 0 deletions(-)
এখানে লক্ষ্য করে দেখুন যে CONTRIBUTING.md ফাইলের ক্ষেত্রে কমিট করার আগে git add কমান্ডটি আপনাকে আর রান করতে হচ্ছেনা। কারণ -a ফ্ল্যাগ ব্যবহার করায় যেসব ফাইলে পরিবর্তন ছিল সেগুলো সবই স্টেইজড হয়ে গিয়েছে। এটা বেশ সুবিধাজনক হলেও সবার সতর্ক থাকা উচিৎ কারণ এর ফলে অনিচ্ছাকৃতভাবে অপ্রয়োজনীয় পরিবর্তন কমিট হয়ে যেতে পারে।
ফাইল রিমুভ করা:
গিট্ থেকে ফাইল রিমুভ করতে হলে সেটিকে ট্র্যাকড ফাইলস অর্থাৎ স্টেজিং এরিয়া থেকে রিমুভ করে তারপর কমিট করতে হবে। git rm কমান্ড এই কাজটিই করে এবং সেই সাথে ফাইলটিকে আপনার ওয়ার্কিং ডিরেক্টরি থেকেও রিমুভ করে দেয় যাতে পরবর্তীতে আনট্র্যাকড ফাইল হিসেবে এটিকে আর দেখা না যায়। আপনি যদি ফাইলটিকে সাধারনভাবে ওয়ার্কিং ডিরেক্টরি থেকে রিমুভ করে দেন, তাহলে git status কমান্ডের আউটপুটে চেঞ্জেস নট স্টেজ ফর কমিট (অর্থাৎ আনস্টেইজড) অংশে সেটিকে দেখাবে:
$ rm PROJECTS.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add/rm ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
deleted: PROJECTS.md
no changes added to commit (use "git add" and/or "git commit -a")
এরপরে আপনি git rm কমান্ড ব্যবহার করে এই ফাইল রিমুভালকে স্টেইজ করতে পারবেন:
$ git rm PROJECTS.md
rm 'PROJECTS.md'
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD ..." to unstage)
deleted: PROJECTS.md
পরেরবার কমিট করার সময় ফাইলটি আর থাকবেনা এবং এটিকে ট্র্যাকও করা হবেনা। আপনি যদি ফাইলে কোনো পরিবর্তন করে থাকেন অথবা সেটি স্টেজিং এরিয়া (staging area) তে নেযা থাকে, তাহলে কিন্তু এটাকে রিমুভ করার জন্য -f অপশন ব্যবহার করতে হবে। এটা এক ধরণের সেফটি ফিচার যাতে করে এমন কোনো ডাটা হারিয়ে না যায় যেটা গিটের কোনো স্ন্যাপশটে সংরক্ষিত নেই।
অনেক সময় এমন হতে পারে যে আপনি ফাইলটিকে শুধুমাত্র আপনার ওয়ার্কিং ডিরেক্টরি তে রেখে স্টেজিং এরিয়া থেকে সরিয়ে ফেলতে চাচ্ছেন। অর্থাৎ ফাইলটি আপনার হার্ড ড্রাইভ -এ থাকবে কিন্তু গিট একে আর ট্র্যাক করবেনা। .gitignore ফাইলে কখনো কিছু অ্যাড করতে ভুলে গেলে (যেমনঃ বিশাল লগ ফাইল অথবা .a কম্পাইলড ফাইলস) এটার দরকার হতে পারে। এই কাজটি করার জন্য –cached অপশন ব্যবহার করতে হবে:
অনেক সময় এমন হতে পারে যে আপনি ফাইলটিকে শুধুমাত্র আপনার ওয়ার্কিং ডিরেক্টরি তে রেখে স্টেজিং এরিয়া থেকে সরিয়ে ফেলতে চাচ্ছেন। অর্থাৎ ফাইলটি আপনার হার্ড ড্রাইভ -এ থাকবে কিন্তু গিট একে আর ট্র্যাক করবেনা। .gitignore ফাইলে কখনো কিছু অ্যাড করতে ভুলে গেলে (যেমনঃ বিশাল লগ ফাইল অথবা .a কম্পাইলড ফাইলস) এটার দরকার হতে পারে। এই কাজটি করার জন্য –cached অপশন ব্যবহার করতে হবে:
$ git rm --cached README
git rm কমান্ডে আর্গুমেন্ট হিসেবে আপনি ফাইলস, ডিরেক্টরি এবং ফাইল-গ্লোব প্যাটার্নসও দিতে পারবেন। যেমন:
$ git rm log/\*.log
এখানে “*” এর আগে ব্যাকস্ল্যাশ (\) চিহ্ন-টি লক্ষ্য করুন। এটার দরকার হয় কারণ আপনার শেল এর ফাইলনেম এক্সপ্যানশন এর পাশাপাশি গিট্ নিজেও ফাইলনেম এক্সপ্যানশন করে থাকে। log/ ডিরেক্টরি তে থাকা .log এক্সটেনশন এর সকল ফাইল-কে এই কমান্ড রিমুভ করে। অথবা আপনি এধরণের কিছু করতে পারেন:
$ git rm \*~
এই কমান্ড যেসব ফাইলের নামের শেষে ‘~’ আছে সেগুলো রিমুভ করে দেয়।
ফাইল মুভ করা:
অন্যান্য ভিসিএস-গুলোর মতো গিট সরাসারি ফাইল মুভমেন্ট ট্র্যাক করেনা। গিটে কোনো ফাইলের নাম পরিবর্তন করলে তার জন্য গিট্ কোনো ধরনের মেটাডাটা সংরক্ষণ করেনা। তবে পরবর্তীতে গিট্কিন্তু খুব সহজেই এই পরিবর্তন ধরে ফেলতে পারে — ফাইল মুভমেন্ট ডিটেক্ট করা নিয়ে আমরা আরো পরে আলোচনা করবো। এসব কারণে গিটের একটি mv কমান্ড আছে এটা ভাবলে একটু গোলমেলে লাগে। গিটে কোনো ফাইলের নাম পরিবর্তন করতে চাইলে এভাবে করতে পারেন:
$ git mv file_from file_to
এই কমান্ড-টি ঠিকভাবে কাজ করে। এটা রান করার পর গিটের স্ট্যাটাস দেখলে লক্ষ্য করবেন যে এখন ফাইলটিকে রিনেইঁমড ফাইল হিসেবে দেখাচ্ছে।
$ git mv README.md README
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD ..." to unstage)
renamed: README.md -> README
এই কাজটি এভাবেও করা সম্ভব:
$ mv README.md README
$ git rm README.md
$ git add README
এই দুইটি উপায়ের যেকোনো একটি ব্যবহার করলেই হবে কারণ গিট্ নিজে থেকেই নাম পরিবর্তনের বিষয়টি বুঝে নেয়। git mv ব্যবহার করাটা সুবিধাজনক কারণ এক্ষেত্রে তিনটি কমান্ডের জায়গায় শুধুমাত্র একটি কমান্ডেই কাজ হয়ে যাচ্ছে। তাছাড়া আপনি চাইলে যেকোনো টুল দিয়ে নাম পরিবর্তন করে শুধু কমিট করার আগে add/rm কমান্ড ব্যবহার করলেই হবে।