একজন বিকাশকারী হিসাবে, আপনি সব সময় Git এর সাথে কাজ করেন।
আপনি কি কখনও এমন একটি বিন্দুতে পৌঁছেছেন যেখানে আপনি বলেছিলেন: "উহ-ওহ, আমি কি করেছি?"
এই পোস্টটি আপনাকে আত্মবিশ্বাসের সাথে ইতিহাস পুনর্লিখন করার সরঞ্জাম দেবে।
আমি এই পোস্টের বিষয়বস্তু কভার একটি লাইভ বক্তৃতা দিয়েছি. আপনি যদি একটি ভিডিও পছন্দ করেন (বা পড়ার পাশাপাশি এটি দেখতে চান) - আপনি এটি খুঁজে পেতে পারেন
আমি গিট সম্পর্কে একটি বই কাজ করছি! আপনি কি প্রাথমিক সংস্করণ পড়তে এবং প্রতিক্রিয়া প্রদান করতে আগ্রহী? আমাকে একটি ইমেল পাঠান: [email protected]
গিটে জিনিসগুলি কীভাবে পূর্বাবস্থায় ফিরিয়ে আনতে হয় তা বোঝার আগে, আপনাকে প্রথমে বুঝতে হবে যে আমরা কীভাবে গিটে পরিবর্তনগুলি রেকর্ড করি । আপনি যদি ইতিমধ্যেই সমস্ত শর্তাদি জানেন তবে নির্দ্বিধায় এই অংশটি এড়িয়ে যান।
সময়মত একটি ফাইল সিস্টেমের স্ন্যাপশট রেকর্ড করার জন্য একটি সিস্টেম হিসাবে গিট সম্পর্কে চিন্তা করা খুব দরকারী। একটি গিট সংগ্রহস্থল বিবেচনা করে, এটির তিনটি "রাষ্ট্র" বা "গাছ" রয়েছে:
সাধারণত, যখন আমরা আমাদের সোর্স কোডে কাজ করি, তখন আমরা একটি ওয়ার্কিং ডির থেকে কাজ করি। একটি ওয়ার্কিং ডির(ইক্টোরি) (বা ওয়ার্কিং ট্রি ) হল আমাদের ফাইল সিস্টেমের যেকোন ডিরেক্টরি যার সাথে একটি রিপোজিটরি যুক্ত আছে।
এটিতে আমাদের প্রকল্পের ফোল্ডার এবং ফাইল রয়েছে এবং .git
নামে একটি ডিরেক্টরিও রয়েছে। আমি .git
ফোল্ডারের বিষয়বস্তু আরও বিস্তারিতভাবে বর্ণনা করেছি
আপনি কিছু পরিবর্তন করার পরে, আপনি সেগুলি আপনার সংগ্রহস্থলে রেকর্ড করতে চাইতে পারেন। একটি রিপোজিটরি (সংক্ষেপে: repo ) হল কমিটগুলির একটি সংগ্রহ, যার প্রত্যেকটি একটি আর্কাইভ যা প্রকল্পের কার্যকারী গাছটি অতীতের তারিখে কেমন ছিল, তা আপনার মেশিনে হোক বা অন্য কারও।
একটি সংগ্রহস্থলে আমাদের কোড ফাইলগুলি ছাড়াও অন্যান্য জিনিসগুলিও অন্তর্ভুক্ত থাকে, যেমন HEAD
, শাখা ইত্যাদি।
এর মধ্যে, আমাদের সূচক বা স্টেজিং এলাকা আছে; এই দুটি পদ বিনিময়যোগ্য। যখন আমরা একটি শাখা checkout
, গিট আমাদের কার্যনির্বাহী ডিরেক্টরিতে সর্বশেষ চেক আউট করা সমস্ত ফাইল বিষয়বস্তু সহ সূচীটি পূরণ করে এবং যখন সেগুলি মূলত চেক আউট করা হয়েছিল তখন সেগুলি কেমন ছিল৷
যখন আমরা git commit
ব্যবহার করি, কমিট তৈরি করা হয় সূচকের অবস্থার উপর ভিত্তি করে।
সুতরাং, সূচক বা স্টেজিং এরিয়া হল পরবর্তী প্রতিশ্রুতির জন্য আপনার খেলার মাঠ। আপনি ইনডেক্সের সাথে আপনি যা চান তা কাজ করতে এবং করতে পারেন, এতে ফাইল যোগ করতে পারেন, এটি থেকে জিনিসগুলি সরাতে পারেন এবং তারপরে আপনি যখন প্রস্তুত হন, আপনি এগিয়ে যান এবং সংগ্রহস্থলে প্রতিশ্রুতিবদ্ধ হন।
হাত পেতে সময় 🙌🏻
একটি নতুন সংগ্রহস্থল শুরু করতে git init
ব্যবহার করুন। 1.txt
নামে একটি ফাইলে কিছু পাঠ্য লিখুন:
উপরে বর্ণিত তিনটি ট্রি স্টেটের মধ্যে 1.txt
এখন কোথায়?
কাজের গাছে, যেহেতু এটি এখনও সূচকে প্রবর্তিত হয়নি।
এটিকে স্টেজ করার জন্য, সূচীতে যোগ করতে, git add 1.txt
ব্যবহার করুন।
এখন, আমরা রিপোজিটরিতে আমাদের পরিবর্তনগুলি কমিট করতে git commit
ব্যবহার করতে পারি।
আপনি একটি নতুন কমিট অবজেক্ট তৈরি করেছেন, যার মধ্যে একটি গাছের জন্য একটি পয়েন্টার রয়েছে যা পুরো কর্মরত গাছের বর্ণনা দেয়। এই ক্ষেত্রে, এটি রুট ফোল্ডারের মধ্যে শুধুমাত্র 1.txt
হতে চলেছে। গাছের একটি পয়েন্টার ছাড়াও, কমিট অবজেক্টে মেটাডেটা অন্তর্ভুক্ত থাকে, যেমন টাইমস্ট্যাম্প এবং লেখকের তথ্য।
গিটের বস্তু সম্পর্কে আরও তথ্যের জন্য (যেমন কমিট এবং গাছ),
(হ্যাঁ, "চেক আউট", শ্লেষ উদ্দেশ্য 😇)
গিট আমাদের এই কমিট অবজেক্টের SHA-1 মানও বলে। আমার ক্ষেত্রে, এটি ছিল c49f4ba
(যা SHA-1 মানের প্রথম 7টি অক্ষর, কিছু স্থান বাঁচাতে)।
আপনি যদি আপনার মেশিনে এই কমান্ডটি চালান, আপনি একটি ভিন্ন SHA-1 মান পাবেন, কারণ আপনি একজন ভিন্ন লেখক; এছাড়াও, আপনি একটি ভিন্ন টাইমস্ট্যাম্পে কমিট তৈরি করবেন।
যখন আমরা রেপো শুরু করি, গিট একটি নতুন শাখা তৈরি করে (ডিফল্টরূপে main
নামকরণ করা হয়)। এবংmain
শাখা আছে. আপনার একাধিক শাখা থাকলে কি হবে? কিভাবে গিট জানে যে কোন শাখা সক্রিয় শাখা?
গিট-এর HEAD
নামক আরেকটি পয়েন্টার রয়েছে, যা একটি শাখার দিকে নির্দেশ করে (সাধারণত) যা একটি কমিটের দিকে নির্দেশ করে। যাইহোক,HEAD
রেপোতে আরও পরিবর্তন প্রবর্তনের সময়!
এখন, আমি আরেকটি তৈরি করতে চাই। তো চলুন একটি নতুন ফাইল তৈরি করি এবং সূচীতে যোগ করি, আগের মতো:
এখন, git commit
ব্যবহার করার সময়। গুরুত্বপূর্ণভাবে, git commit
দুটি জিনিস করে:
প্রথমত, এটি একটি কমিট অবজেক্ট তৈরি করে, তাই গিটের অভ্যন্তরীণ অবজেক্ট ডাটাবেসের মধ্যে একটি অনুরূপ SHA-1 মান সহ একটি অবজেক্ট রয়েছে। এই নতুন কমিট অবজেক্টটি প্যারেন্ট কমিটের দিকেও নির্দেশ করে। এটি সেই প্রতিশ্রুতি যা HEAD
নির্দেশ করেছিল যখন আপনি git commit
কমান্ড লিখেছিলেন।
দ্বিতীয়ত, git commit
সক্রিয় শাখার পয়েন্টারকে স্থানান্তরিত করে — আমাদের ক্ষেত্রে, এটি main
হবে, নতুন তৈরি কমিট অবজেক্টের দিকে নির্দেশ করতে।
ইতিহাস পুনর্লিখনের জন্য, আসুন একটি প্রতিশ্রুতি প্রবর্তনের প্রক্রিয়াটিকে পূর্বাবস্থায় ফিরিয়ে নিয়ে শুরু করি। এর জন্য, আমরা git reset
কমান্ডটি জানব, একটি সুপার পাওয়ারফুল টুল।
git reset --soft
সুতরাং আপনি আগে যে শেষ ধাপটি করেছিলেন তা ছিল git commit
, যার অর্থ আসলে দুটি জিনিস — গিট একটি কমিট অবজেক্ট তৈরি করেছে এবং main
, সক্রিয় শাখাকে সরিয়ে নিয়েছে। এই ধাপটিকে পূর্বাবস্থায় ফেরাতে, কমান্ডটি ব্যবহার করুন git reset --soft HEAD~1
।
সিনট্যাক্স HEAD~1
HEAD
এর প্রথম প্যারেন্টকে বোঝায়। আমার যদি কমিট-গ্রাফে একাধিক কমিট থাকে, তাহলে বলুন "কমিট 3" নির্দেশ করে "কমিট 2" এর দিকে নির্দেশ করে, যেটি পরিবর্তে, "কমিট 1" এর দিকে নির্দেশ করে।
এবং বলুন HEAD
"কমিট 3" এর দিকে ইশারা করছিল। আপনি "কমিট 2" উল্লেখ করতে HEAD~1
ব্যবহার করতে পারেন, এবং HEAD~2
"কমিট 1" উল্লেখ করবে।
সুতরাং, কমান্ডে ফিরে যান: git reset --soft HEAD~1
এই কমান্ডটি গিটকে HEAD
যা নির্দেশ করছে তা পরিবর্তন করতে বলে। (দ্রষ্টব্য: নীচের চিত্রগুলিতে, আমি " HEAD
যা নির্দেশ করছে" এর জন্য *HEAD
ব্যবহার করি)। আমাদের উদাহরণে, HEAD
main
নির্দেশ করছে। তাই গিট শুধুমাত্র main
পয়েন্টার পরিবর্তন করে HEAD~1
নির্দেশ করবে। অর্থাৎ, main
"কমিট 1" নির্দেশ করবে।
যাইহোক, এই আদেশটি সূচকের অবস্থা বা কার্যকারী গাছকে প্রভাবিত করেনি । সুতরাং আপনি যদি git status
ব্যবহার করেন তবে আপনি দেখতে পাবেন যে 2.txt
মঞ্চস্থ হয়েছে, ঠিক যেমন আপনি git commit
চালানোর আগে।
git log?
এটি HEAD
থেকে শুরু হবে, main
যাবেন এবং তারপর "কমিট 1" এ যাবে। লক্ষ্য করুন যে এর অর্থ হল "কমিট 2" আমাদের ইতিহাস থেকে আর পৌঁছানো যায় না।
এর মানে কি "কমিট 2" এর কমিট অবজেক্ট মুছে ফেলা হয়েছে? 🤔
না, এটা মুছে ফেলা হয় নি. এটি এখনও অবজেক্টের গিট এর অভ্যন্তরীণ অবজেক্ট ডাটাবেসের মধ্যে থাকে।
আপনি যদি বর্তমান ইতিহাসকে এখনই ধাক্কা দেন, git push
ব্যবহার করে, গিট রিমোট সার্ভারে "কমিট 2" পুশ করবে না, তবে কমিট অবজেক্টটি আপনার সংগ্রহস্থলের স্থানীয় অনুলিপিতে এখনও বিদ্যমান রয়েছে।
এখন, আবার কমিট করুন — এবং মূল "কমিট 2" থেকে এই নতুন অবজেক্টটিকে আলাদা করতে "কমিট 2.1" এর কমিট মেসেজ ব্যবহার করুন:
কেন "কমিট 2" এবং "কমিট 2.1" আলাদা? এমনকি যদি আমরা একই প্রতিশ্রুতি বার্তা ব্যবহার করে, এবং যদিও তারা নির্দেশ করে1.txt
এবং 2.txt
সমন্বিত রুট ফোল্ডারের), তাদের এখনও বিভিন্ন টাইমস্ট্যাম্প রয়েছে, কারণ সেগুলি বিভিন্ন সময়ে তৈরি করা হয়েছিল।
উপরের অঙ্কনে, আমি আপনাকে মনে করিয়ে দেওয়ার জন্য "কমিট 2" রেখেছি যে এটি এখনও গিটের অভ্যন্তরীণ অবজেক্ট ডাটাবেসে বিদ্যমান। "কমিট 2" এবং "কমিট 2.1" উভয়ই এখন "কমিট 1" নির্দেশ করে, কিন্তু শুধুমাত্র "কমিট 2.1" HEAD
থেকে পৌঁছানো যায়।
এটি এমনকি পিছিয়ে যাওয়ার এবং আরও পূর্বাবস্থায় যাওয়ার সময়। এইবার, git reset --mixed HEAD~1
(দ্রষ্টব্য: --mixed
হল git reset
জন্য ডিফল্ট সুইচ)।
এই কমান্ডটি git reset --soft HEAD~1
। অর্থাত্ HEAD
এখন যেটি নির্দেশ করছে তার পয়েন্টার নেয়, যা main
শাখা, এবং এটিকে HEAD~1
এ সেট করে, আমাদের উদাহরণে - "কমিট 1"।
এরপরে, গিট আরও এগিয়ে যায়, কার্যকরভাবে আমরা সূচীতে করা পরিবর্তনগুলিকে পূর্বাবস্থায় ফিরিয়ে আনে। অর্থাৎ, সূচক পরিবর্তন করা যাতে এটি বর্তমান HEAD
এর সাথে মিলে যায়, প্রথম ধাপে সেট করার পরে নতুন HEAD
।
যদি আমরা git reset --mixed HEAD~1
, এর মানে হল HEAD
HEAD~1
("কমিট 1") এ সেট করা হবে, এবং তারপর গিট "কমিট 1" এর অবস্থার সাথে সূচকের সাথে মিলবে — এই ক্ষেত্রে, এটি মানে 2.txt
আর সূচকের অংশ হবে না।
মূল "কমিট 2" এর অবস্থার সাথে একটি নতুন প্রতিশ্রুতি তৈরি করার সময় এসেছে৷ এইবার আমাদের এটি তৈরি করার আগে আবার 2.txt
স্টেজ করতে হবে:
চালিয়ে যান, আরও পূর্বাবস্থায় ফেরান!
এগিয়ে যান এবং git reset --hard HEAD~1
আবার, গিট --soft
পর্যায় দিয়ে শুরু হয়, যা কিছু HEAD
নির্দেশ করে ( main
), HEAD~1
("Commit 1") এর দিকে সেটিং করে।
এ পর্যন্ত সব ঠিকই.
এর পরে, HEAD
এর সাথে সূচকের সাথে মিল রেখে --mixed
পর্যায়ে চলে যান। অর্থাৎ, গিট 2.txt
এর স্টেজিং পূর্বাবস্থায় ফিরিয়ে আনে।
এটা --hard
পদক্ষেপের সময় যেখানে গিট আরও এগিয়ে যায় এবং সূচকের পর্যায়ের সাথে কাজের ডিরকে মেলে। এই ক্ষেত্রে, এর অর্থ হল ওয়ার্কিং ডির থেকে 2.txt
মুছে ফেলা।
(** দ্রষ্টব্য: এই নির্দিষ্ট ক্ষেত্রে, ফাইলটি আনট্র্যাক করা হয়েছে, তাই এটি ফাইল সিস্টেম থেকে মুছে ফেলা হবে না; যদিও git reset
বোঝার জন্য এটি সত্যিই গুরুত্বপূর্ণ নয়)।
তাই গিটে একটি পরিবর্তন প্রবর্তন করতে, আপনার তিনটি ধাপ আছে। আপনি কাজের ডাইর, ইনডেক্স বা স্টেজিং এরিয়া পরিবর্তন করেন এবং তারপর আপনি সেই পরিবর্তনগুলির সাথে একটি নতুন স্ন্যাপশট করেন। এই পরিবর্তনগুলি পূর্বাবস্থায় ফেরাতে :
git reset --soft
ব্যবহার করি, তাহলে আমরা কমিট ধাপকে পূর্বাবস্থায় ফিরিয়ে আনব।
git reset --mixed
ব্যবহার করি, তাহলে আমরা স্টেজিং ধাপকে পূর্বাবস্থায় ফিরিয়ে আনব।
git reset --hard
ব্যবহার করি, তাহলে আমরা কাজের ডির-এ পরিবর্তনগুলি পূর্বাবস্থায় ফিরিয়ে আনব। তাই একটি বাস্তব-জীবনের দৃশ্যে, একটি ফাইলে "আমি গিটকে ভালোবাসি" লিখুন ( love.txt
), যেমন আমরা সবাই গিটকে ভালোবাসি 😍। এগিয়ে যান, স্টেজ করুন এবং এটিও কমিট করুন:
ওহ, উফ!
আসলে, আমি চাইনি তুমি এটা কর।
আমি আসলে আপনাকে যা করতে চেয়েছিলাম তা হল এই ফাইলটিতে এটি করার আগে আরও কিছু প্রেমের শব্দ লিখুন।
আপনি কি করতে পারেন?
ঠিক আছে, এটি কাটিয়ে ওঠার একটি উপায় হ'ল git reset --mixed HEAD~1
ব্যবহার করা, আপনার নেওয়া কমিটিং এবং স্টেজিং অ্যাকশন উভয়কেই কার্যকরভাবে পূর্বাবস্থায় ফিরিয়ে আনা:
তাই আবার "কমিট 1" এর main
পয়েন্ট, এবং love.txt
আর সূচকের অংশ নয়। যাইহোক, ফাইলটি কর্মরত ডিরে রয়ে গেছে। আপনি এখন এগিয়ে যেতে পারেন, এবং এতে আরও সামগ্রী যোগ করতে পারেন:
এগিয়ে যান, স্টেজ করুন এবং আপনার ফাইল কমিট করুন:
ভালো হয়েছে 👏🏻
আপনি "কমিট 2.4" এর এই পরিষ্কার, সুন্দর ইতিহাস পেয়েছেন "কমিট 1" এর দিকে নির্দেশ করে।
এখন আমাদের টুলবক্সে একটি নতুন টুল আছে, git reset
💪🏻
এই টুলটি সুপার, সুপার উপযোগী, এবং আপনি এটির সাহায্যে প্রায় সবকিছুই করতে পারেন। এটি সর্বদা ব্যবহার করার জন্য সবচেয়ে সুবিধাজনক সরঞ্জাম নয়, তবে আপনি যদি এটি সাবধানে ব্যবহার করেন তবে এটি প্রায় কোনও পুনর্লিখন-ইতিহাস পরিস্থিতি সমাধান করতে সক্ষম।
নতুনদের জন্য, আমি সুপারিশ করছি শুধুমাত্র git reset
ব্যবহার করার জন্য প্রায় যেকোনো সময় আপনি গিট এ পূর্বাবস্থায় ফেরাতে চান। একবার আপনি এটির সাথে স্বাচ্ছন্দ্য বোধ করলে, এটি অন্যান্য সরঞ্জামগুলিতে যাওয়ার সময়।
আসুন আরেকটি ঘটনা বিবেচনা করা যাক।
new.txt
নামে একটি নতুন ফাইল তৈরি করুন; পর্যায় এবং প্রতিশ্রুতি:
উফ। আসলে, এটি একটি ভুল. আপনি main
ছিলেন, এবং আমি চেয়েছিলাম আপনি একটি বৈশিষ্ট্য শাখায় এই প্রতিশ্রুতি তৈরি করুন। আমার খারাপ 😇
আমি এই পোস্ট থেকে আপনি নিতে চাই দুটি সবচেয়ে গুরুত্বপূর্ণ টুল আছে. দ্বিতীয়টি হল git reset
। প্রথম এবং অনেক বেশি গুরুত্বপূর্ণ হল বর্তমান অবস্থা বনাম আপনি যে রাজ্যে থাকতে চান তা হোয়াইটবোর্ড করা ।
এই দৃশ্যের জন্য, বর্তমান অবস্থা এবং পছন্দসই অবস্থা দেখতে এরকম:
আপনি তিনটি পরিবর্তন লক্ষ্য করবেন:
বর্তমান অবস্থায় "কমিট 3" (নীল এক), কিন্তু কাঙ্খিত অবস্থায় "কমিট 2.4" এর main
পয়েন্ট।
feature
শাখা বর্তমান অবস্থায় বিদ্যমান নেই, তবুও এটি বিদ্যমান এবং পছন্দসই অবস্থায় "কমিট 3" নির্দেশ করে।
HEAD
বর্তমান অবস্থায় main
দিকে নির্দেশ করে এবং কাঙ্খিত অবস্থায় feature
দেখায়।
আপনি যদি এটি আঁকতে পারেন এবং আপনি কীভাবে git reset
ব্যবহার করতে জানেন তবে আপনি অবশ্যই এই পরিস্থিতি থেকে নিজেকে বের করে আনতে পারেন।
তাই আবার, সবচেয়ে গুরুত্বপূর্ণ জিনিস একটি শ্বাস নিতে এবং এটি আঁকতে হয়.
উপরের অঙ্কনটি পর্যবেক্ষণ করে, আমরা কীভাবে বর্তমান অবস্থা থেকে কাঙ্ক্ষিত অবস্থায় যেতে পারি?
অবশ্যই কয়েকটি ভিন্ন উপায় আছে, তবে আমি প্রতিটি দৃশ্যের জন্য শুধুমাত্র একটি বিকল্প উপস্থাপন করব। পাশাপাশি অন্যান্য বিকল্পগুলির সাথে খেলতে বিনা দ্বিধায়।
আপনি git reset --soft HEAD~1
ব্যবহার করে শুরু করতে পারেন। এটি পূর্ববর্তী কমিট, "কমিট 2.4" এর দিকে নির্দেশ করার জন্য main
সেট করবে:
বর্তমান-বনাম-কাঙ্খিত চিত্রটি আবার উঁকি দিয়ে, আপনি দেখতে পাচ্ছেন যে আপনার একটি নতুন শাখা দরকার, তাই না? আপনি এটির জন্য git switch -c feature
বা git checkout -b feature
ব্যবহার করতে পারেন (যা একই কাজ করে):
এই কমান্ডটি নতুন শাখার দিকে নির্দেশ করার জন্য HEAD
আপডেট করে।
যেহেতু আপনি git reset --soft
ব্যবহার করেছেন, আপনি সূচী পরিবর্তন করেননি, তাই এটিতে বর্তমানে ঠিক সেই অবস্থা রয়েছে যা আপনি করতে চান — কতটা সুবিধাজনক! আপনি কেবল feature
শাখায় প্রতিশ্রুতিবদ্ধ করতে পারেন:
এবং আপনি পছন্দসই অবস্থায় পেয়েছেন 🎉
অতিরিক্ত ক্ষেত্রে আপনার জ্ঞান প্রয়োগ করতে প্রস্তুত?
love.txt
এ কিছু পরিবর্তন যোগ করুন, এবং cool.txt
নামে একটি নতুন ফাইল তৈরি করুন। তাদের স্টেজ করুন এবং প্রতিশ্রুতি দিন:
ওহ, ওহো, আসলে আমি চেয়েছিলাম আপনি দুটি আলাদা কমিট তৈরি করুন, প্রতিটি পরিবর্তনের সাথে একটি 🤦🏻
এই এক নিজেকে চেষ্টা করতে চান?
আপনি প্রতিশ্রুতিবদ্ধ এবং স্টেজিং পদক্ষেপগুলি পূর্বাবস্থায় ফিরিয়ে আনতে পারেন:
এই কমান্ড অনুসরণ করে, সূচীতে আর এই দুটি পরিবর্তন অন্তর্ভুক্ত করা হয় না, তবে তারা উভয়ই এখনও আপনার ফাইল সিস্টেমে রয়েছে। তাই এখন, যদি আপনি শুধুমাত্র love.txt
স্টেজ করেন, তাহলে আপনি আলাদাভাবে এটি কমিট করতে পারেন, এবং তারপর cool.txt
এর জন্য একই কাজ করতে পারেন:
চমৎকার 😎
কিছু টেক্সট সহ একটি নতুন ফাইল ( new_file.txt
) তৈরি করুন এবং love.txt
এ কিছু টেক্সট যোগ করুন। উভয় পরিবর্তনের পর্যায়, এবং তাদের প্রতিশ্রুতিবদ্ধ:
উফ 🙈🙈
তাই এই সময়, আমি এটি অন্য শাখায় হতে চেয়েছিলাম, কিন্তু একটি নতুন শাখা নয়, বরং একটি ইতিমধ্যে বিদ্যমান শাখা.
তো তুমি কি করতে পার?
আমি আপনাকে একটি ইঙ্গিত দেব. উত্তর সত্যিই সংক্ষিপ্ত এবং সত্যিই সহজ. আমরা প্রথমে কি করব?
না, reset
নয়। আমরা আঁকি. এটি করা প্রথম জিনিস, কারণ এটি অন্য সবকিছুকে অনেক সহজ করে তুলবে। তাই এই বর্তমান অবস্থা:
আর কাঙ্খিত রাষ্ট্র?
আপনি কিভাবে বর্তমান অবস্থা থেকে কাঙ্ক্ষিত অবস্থায় পেতে পারেন, সবচেয়ে সহজ হবে কি?
সুতরাং একটি উপায় হল git reset
ব্যবহার করা যেমন আপনি আগে করেছিলেন, তবে আরেকটি উপায় আছে যা আমি চাই আপনি চেষ্টা করুন।
প্রথমে, existing
শাখায় নির্দেশ করতে HEAD
সরান:
স্বজ্ঞাতভাবে, আপনি যা করতে চান তা হল নীল প্রতিশ্রুতিতে প্রবর্তিত পরিবর্তনগুলি গ্রহণ করুন এবং existing
শাখার উপরে এই পরিবর্তনগুলি ("কপি-পেস্ট") প্রয়োগ করুন। এবং গিট শুধু যে জন্য একটি টুল আছে.
এই কমিট এবং এর প্যারেন্ট কমিটের মধ্যে প্রবর্তিত পরিবর্তনগুলি নিতে এবং শুধুমাত্র সক্রিয় শাখায় এই পরিবর্তনগুলি প্রয়োগ করতে গিটকে জিজ্ঞাসা করতে, আপনি git cherry-pick
ব্যবহার করতে পারেন। এই কমান্ডটি নির্দিষ্ট রিভিশনে প্রবর্তিত পরিবর্তনগুলি গ্রহণ করে এবং সেগুলি সক্রিয় কমিটে প্রয়োগ করে।
এটি একটি নতুন কমিট অবজেক্টও তৈরি করে এবং এই নতুন অবজেক্টের দিকে নির্দেশ করতে সক্রিয় শাখা আপডেট করে।
উপরের উদাহরণে, আমি তৈরি করা কমিটের SHA-1 শনাক্তকারী নির্দিষ্ট করেছি, কিন্তু আপনি git cherry-pick main
ব্যবহার করতে পারেন, কারণ যে প্রতিশ্রুতিটির পরিবর্তনগুলি আমরা প্রয়োগ করছি সেটি একটি main
নির্দেশ করছে।
কিন্তু আমরা চাই না এই পরিবর্তনগুলো main
শাখায় থাকুক। git cherry-pick
শুধুমাত্র existing
শাখায় পরিবর্তনগুলি প্রয়োগ করেছে। কিভাবে আপনি main
থেকে তাদের সরাতে পারেন?
একটি উপায় হল main
এ ফিরে switch
এবং তারপর git reset --hard HEAD~1
:
তুমি এটি করেছিলে! 💪🏻
উল্লেখ্য যে git cherry-pick
প্রকৃতপক্ষে নির্দিষ্ট কমিট এবং এর প্যারেন্টের মধ্যে পার্থক্য গণনা করে এবং তারপরে তাদের সক্রিয় প্রতিশ্রুতিতে প্রয়োগ করে। এর মানে হল যে কখনও কখনও, গিট সেই পরিবর্তনগুলি প্রয়োগ করতে সক্ষম হবে না কারণ আপনি একটি দ্বন্দ্ব পেতে পারেন, তবে এটি অন্য পোস্টের জন্য একটি বিষয়।
এছাড়াও, মনে রাখবেন যে আপনি গিটকে যেকোন কমিটে প্রবর্তিত পরিবর্তনগুলিকে cherry-pick
করতে বলতে পারেন, শুধুমাত্র একটি শাখা দ্বারা উল্লেখিত কমিট নয়।
আমরা একটি নতুন টুল অর্জন করেছি, তাই আমাদের বেল্টের নিচে git cherry-pick
এবং git reset
আছে।
ঠিক আছে, তাই অন্য দিন, অন্য রেপো, অন্য সমস্যা।
একটি প্রতিশ্রুতি তৈরি করুন:
এবং এটি দূরবর্তী সার্ভারে push
:
উম, উফ 😓…
আমি শুধু কিছু লক্ষ্য করেছি. সেখানে একটি টাইপো আছে. আমি লিখেছিলাম This is more tezt
এর পরিবর্তে This is more text
। উফফফ তাহলে এখন বড় সমস্যা কি? আমি ed push
, যার মানে অন্য কেউ ইতিমধ্যেই এই পরিবর্তন pull
হতে পারে.
যদি আমি git reset
ব্যবহার করে সেই পরিবর্তনগুলিকে ওভাররাইড করি, যেমনটি আমরা এখন পর্যন্ত করেছি, আমাদের আলাদা ইতিহাস থাকবে এবং সমস্ত নরক ভেঙে যেতে পারে। আপনি রেপোর আপনার নিজের অনুলিপিটি যতক্ষণ চান ততক্ষণ পুনরায় লিখতে পারেন যতক্ষণ না আপনি এটিকে push
।
একবার আপনি পরিবর্তনটি push
, আপনাকে অবশ্যই নিশ্চিত হতে হবে যে আপনি যদি ইতিহাস পুনর্লিখন করতে যাচ্ছেন তবে অন্য কেউ সেই পরিবর্তনগুলি নিয়ে আসেনি।
বিকল্পভাবে, আপনি git revert
নামে আরেকটি টুল ব্যবহার করতে পারেন। এই কমান্ডটি আপনি যে প্রতিশ্রুতি প্রদান করছেন তা গ্রহণ করে এবং এর প্যারেন্ট কমিট থেকে ডিফ গণনা করে, ঠিক যেমন git cherry-pick
, কিন্তু এই সময়, এটি বিপরীত পরিবর্তনগুলি গণনা করে।
সুতরাং যদি নির্দিষ্ট কমিটে আপনি একটি লাইন যোগ করেন, বিপরীতটি লাইনটি মুছে ফেলবে এবং এর বিপরীতে।
git revert
একটি নতুন কমিট অবজেক্ট তৈরি করেছে, যার মানে এটি ইতিহাসের একটি সংযোজন। git revert
ব্যবহার করে, আপনি ইতিহাস পুনর্লিখন করেননি। আপনি আপনার অতীতের ভুল স্বীকার করেছেন, এবং এই প্রতিশ্রুতি হল একটি স্বীকৃতি যে আপনি একটি ভুল করেছেন এবং এখন আপনি এটি ঠিক করেছেন।
কেউ কেউ বলবেন এটি আরও পরিণত উপায়। কেউ কেউ বলবে যে এটি এতটা পরিষ্কার ইতিহাস নয় যতটা আপনি পাবেন যদি আপনি পূর্ববর্তী প্রতিশ্রুতিটি পুনরায় লেখার জন্য git reset
ব্যবহার করেন। কিন্তু ইতিহাস পুনর্লিখন এড়াতে এটি একটি উপায়।
আপনি এখন টাইপো ঠিক করতে পারেন এবং আবার কমিট করতে পারেন:
আপনার টুলবক্স এখন একটি নতুন চকচকে টুল দিয়ে লোড হয়েছে, revert
:
কিছু কাজ সম্পন্ন করুন, কিছু কোড লিখুন এবং এটি love.txt
এ যোগ করুন। এই পরিবর্তনটি মঞ্চস্থ করুন, এবং এটি প্রতিশ্রুতিবদ্ধ করুন:
আমি আমার মেশিনে একই কাজ করেছি, এবং আমি পূর্ববর্তী কমান্ডগুলিতে স্ক্রোল করার জন্য আমার কীবোর্ডে Up
তীর কীটি ব্যবহার করেছি, এবং তারপরে আমি Enter
, এবং... বাহ।
উফফফ
আমি কি শুধু git reset --hard
ব্যবহার করেছি? 😨
আসলে কি হয়েছিল? গিট পয়েন্টারটিকে HEAD~1
এ নিয়ে গেছে, তাই আমার সমস্ত মূল্যবান কাজের সাথে শেষ প্রতিশ্রুতিটি বর্তমান ইতিহাস থেকে পৌঁছানো সম্ভব নয়। গিট স্টেজিং এরিয়া থেকে সমস্ত পরিবর্তন আনস্টেজ করেছে, এবং তারপর স্টেজিং এরিয়ার অবস্থার সাথে ওয়ার্কিং ডিরকে মেলেছে।
অর্থাৎ, সবকিছু মিলে এই রাজ্যে যেখানে আমার কাজ… চলে গেছে।
পাগল আউট সময়. বিব্রতকর
কিন্তু, সত্যিই, ভয় পাওয়ার কারণ আছে কি? সত্যিই না... আমরা স্বচ্ছন্দ মানুষ। আমরা কি করি? ভাল, স্বজ্ঞাতভাবে, প্রতিশ্রুতি কি সত্যিই, সত্যিই চলে গেছে? না। কেন নয়? এটি এখনও গিটের অভ্যন্তরীণ ডাটাবেসের ভিতরে বিদ্যমান।
যদি আমি কেবল জানতাম যে এটি কোথায়, আমি SHA-1 মানটি জানতাম যা এই প্রতিশ্রুতিটিকে চিহ্নিত করে, আমরা এটি পুনরুদ্ধার করতে পারি। আমি এমনকি পূর্বাবস্থাকে পূর্বাবস্থায় ফিরিয়ে আনতে পারি এবং এই প্রতিশ্রুতিতে পুনরায় reset
।
সুতরাং আমার এখানে সত্যিই যে জিনিসটি দরকার তা হল "মুছে ফেলা" কমিটের SHA-1।
তাই প্রশ্ন হল, আমি কিভাবে এটি খুঁজে পেতে পারি? git log
দরকারী হবে?
সত্যিই ভাল না. git log
HEAD
এ যাবে, যা main
এর দিকে নির্দেশ করে, যা আমরা যে কমিট খুঁজছি তার প্যারেন্ট কমিটকে নির্দেশ করে। তারপর, git log
প্যারেন্ট চেইনের মাধ্যমে ফিরে আসবে, যা আমার মূল্যবান কাজের সাথে প্রতিশ্রুতি অন্তর্ভুক্ত করে না।
সৌভাগ্যক্রমে, গিট তৈরি করা খুব স্মার্ট লোকেরা আমাদের জন্য একটি ব্যাকআপ প্ল্যান তৈরি করেছে এবং এটিকে বলা হয় reflog
।
আপনি গিট এর সাথে কাজ করার সময়, আপনি যখনই HEAD
পরিবর্তন করেন, যা আপনি git reset
ব্যবহার করে করতে পারেন, তবে অন্যান্য কমান্ড যেমন git switch
বা git checkout
, গিট reflog
একটি এন্ট্রি যোগ করে।
আমরা আমাদের প্রতিশ্রুতি খুঁজে পেয়েছি! এটি 0fb929e
দিয়ে শুরু হয়।
আমরা এটির সাথে এর "ডাকনাম" - HEAD@{1}
দ্বারাও সম্পর্কযুক্ত হতে পারি। তাই যেমন গিট HEAD
এর প্রথম অভিভাবকের কাছে যাওয়ার জন্য HEAD~1
ব্যবহার করে এবং HEAD
এর দ্বিতীয় অভিভাবককে বোঝাতে HEAD~2
ব্যবহার করে এবং আরও অনেক কিছু, গিট HEAD
এর প্রথম reflog অভিভাবককে বোঝাতে HEAD@{1}
ব্যবহার করে, যেখানে HEAD
পূর্ববর্তী ধাপে নির্দেশ করেছে।
আমরা git rev-parse
এর মান দেখাতেও বলতে পারি:
reflog
দেখার আরেকটি উপায় হল git log -g
ব্যবহার করে, যা git log
আসলে reflog
বিবেচনা করতে বলে:
আমরা উপরে দেখতে পাচ্ছি যে reflog
, ঠিক যেমন HEAD
, main
দিকে নির্দেশ করে, যা "কমিট 2" নির্দেশ করে। কিন্তু reflog
এ সেই এন্ট্রির অভিভাবক "কমিট 3"-এর দিকে নির্দেশ করে।
তাই "কমিট 3" এ ফিরে যেতে, আপনি শুধু git reset --hard HEAD@{1}
(বা "কমিট 3" এর SHA-1 মান) ব্যবহার করতে পারেন:
এবং এখন, যদি আমরা git log
:
আমরা দিন সংরক্ষণ! 🎉👏🏻
আমি আবার এই কমান্ড ব্যবহার করলে কি হবে? এবং git commit --reset HEAD@{1}
? গিট শেষ reset
আগে যেখানে HEAD
নির্দেশ করছিল সেখানে HEAD
সেট করবে, যার অর্থ "কমিট 2"। আমরা সারাদিন চলতে পারি:
এখন আমাদের টুলবক্সের দিকে তাকানো, এটি এমন সরঞ্জামগুলির সাথে লোড করা হয়েছে যা আপনাকে অনেকগুলি ক্ষেত্রে সমাধান করতে সাহায্য করতে পারে যেখানে গিট-এ কিছু ভুল হয়:
এই সরঞ্জামগুলির সাহায্যে, আপনি এখন আরও ভালভাবে বুঝতে পারবেন কিভাবে গিট কাজ করে। আরও অনেক টুল রয়েছে যা আপনাকে ইতিহাসকে বিশেষভাবে পুনঃলিখন করার অনুমতি দেবে, git rebase
), কিন্তু আপনি ইতিমধ্যে এই পোস্টে অনেক কিছু শিখেছেন। ভবিষ্যতের পোস্টগুলিতে, আমি git rebase
ডুব দেব।
সবচেয়ে গুরুত্বপূর্ণ টুল, এই টুলবক্সে তালিকাভুক্ত পাঁচটি টুলের চেয়েও বেশি গুরুত্বপূর্ণ, হল বর্তমান পরিস্থিতি বনাম পছন্দসই একটিকে হোয়াইটবোর্ড করা। এটিতে আমাকে বিশ্বাস করুন, এটি প্রতিটি পরিস্থিতিকে কম ভয়ঙ্কর এবং সমাধানটিকে আরও স্পষ্ট করে তুলবে।
আমি এই পোস্টের বিষয়বস্তু কভার একটি লাইভ বক্তৃতা দিয়েছি. আপনি যদি একটি ভিডিও পছন্দ করেন (বা পড়ার পাশাপাশি এটি দেখতে চান) - আপনি এটি খুঁজে পেতে পারেন
সাধারণভাবে,
ওমের তেল আবিব বিশ্ববিদ্যালয় থেকে ভাষাবিজ্ঞানে এমএ করেছেন এবং তিনি এর স্রষ্টা
এখানে প্রথম প্রকাশিত