কীভাবে গিট রিসেট করবেন - একটি উপ-ডিরেক্টরিতে?


196

আপডেট : গিট ২.২৩ (আগস্ট 2019) এর সাথে একটি নতুন আদেশ রয়েছে git restoreযা এটি করে, স্বীকৃত উত্তরটি দেখুন

আপডেট : এটি গিট ১.৮.৩ অনুসারে আরও স্বজ্ঞাতভাবে কাজ করবে, আমার নিজের উত্তর দেখুন

নিম্নলিখিত ব্যবহারের ক্ষেত্রেটি কল্পনা করুন: আমি আমার গিট ওয়ার্কিং ট্রিের একটি নির্দিষ্ট সাব-ডিরেক্টরিতে সমস্ত পরিবর্তন থেকে মুক্তি পেতে চাই এবং অন্যান্য সমস্ত সাব-ডিরেক্টরিকে অক্ষত রেখেছি।

এই অপারেশনের জন্য সঠিক গিট কমান্ড কী?

নীচের স্ক্রিপ্টটি সমস্যার চিত্র তুলে ধরেছে। How to make filesমন্তব্যের নীচে সঠিক কমান্ড প্রবেশ করান - বর্তমান কমান্ডটি সেই ফাইলটি পুনরুদ্ধার করবে a/c/acযা স্পার্স চেকআউট দ্বারা বাদ দেওয়া হবে বলে মনে করা হচ্ছে। নোট করুন যে আমি স্পষ্টভাবে পুনরুদ্ধার করতে চাই নাa/a এবং a/b, আমি কেবল "জানি" aএবং নীচের সমস্ত কিছু পুনরুদ্ধার করতে চাই। সম্পাদনা : এবং আমিও "জানি" না b, বা অন্যান্য ডিরেক্টরিগুলিও একই স্তরে বাস করে a

#!/bin/sh

rm -rf repo; git init repo; cd repo
for f in a b; do
  for g in a b c; do
    mkdir -p $f/$g
    touch $f/$g/$f$g
    git add $f/$g
    git commit -m "added $f/$g"
  done
done
git config core.sparsecheckout true
echo a/a > .git/info/sparse-checkout
echo a/b >> .git/info/sparse-checkout
echo b/a >> .git/info/sparse-checkout
git read-tree -m -u HEAD
echo "After read-tree:"
find * -type f

rm a/a/aa
rm a/b/ab
echo >> b/a/ba
echo "After modifying:"
find * -type f
git status

# How to make files a/* reappear without changing b and without recreating a/c?
git checkout -- a

echo "After checkout:"
git status
find * -type f

3
একটি সম্পর্কে কি git stash && git stash drop?
চার্লসবি

1
কি git checkout -- /path/to/subdir/?
ইবারবেউ

3
@ চারেলসবি: git stashকোনও পথের তর্কটি গ্রহণ করে না ...
krlMLr

@ আইবারবেউ: না বিচ্ছিন্ন চেকআউট দ্বারা বাদ দেওয়া ফাইলগুলিও যুক্ত করবে।
krlmlr

1
@ চারলেস বেইলি: তারপরে কেন একটি রেডিও বোতাম পড়ছে "বিশ্বাসযোগ্য এবং / অথবা অফিসিয়াল উত্স থেকে উত্তর অঙ্কনের সন্ধান করছেন" " অনুগ্রহ সংলাপে? আমি নিজে টাইপ করিনি! "গিট রিসেট উপ-ডিরেক্টরি" (উদ্ধৃতি ব্যতীত) গুগল করার চেষ্টা করুন এবং প্রথম 3 পজিশনে কী আছে তা দেখুন। নিশ্চিতভাবে একটি কার্নেল.অর্গ মেইলিং তালিকায় একটি বার্তা পাওয়া আরও কঠিন হবে। - এছাড়াও, আমার কাছে এটি এখনও পরিষ্কার হয় না যে এই আচরণটি কোনও বাগ বা কোনও বৈশিষ্ট্য।
krlMLr

উত্তর:


161

গিট 2.23 (আগস্ট 2019) এর সাথে আপনার কাছে নতুন কমান্ড রয়েছেgit restore

git restore --source=HEAD --staged --worktree -- aDirectory
# or, shorter
git restore -s@ -SW  -- aDirectory

এটি সূচী এবং কার্যনির্বাহী উভয়ই HEADসামগ্রী হিসাবে প্রতিস্থাপন করবে যেমন একটি ইচ্ছা reset --hard, তবে একটি নির্দিষ্ট পথের জন্য।


আসল উত্তর (২০১৩)

নোট (যেমন মন্তব্য দ্বারা ড্যান Fabulich ) যে:

  • git checkout -- <path> একটি হার্ড রিসেট করে না: এটি মঞ্চযুক্ত বিষয়বস্তুগুলির সাথে কাজ করা গাছের সামগ্রীর পরিবর্তে।
  • git checkout HEAD -- <path>HEADপ্রতিশ্রুতি থেকে সংস্করণ অনুসারে সূচি এবং কার্যকারী গাছ উভয়কে প্রতিস্থাপন করে একটি পাথের জন্য হার্ড রিসেট করে ।

Ajedi32 দ্বারা উত্তর হিসাবে , উভয় চেকআউট ফর্ম লক্ষ্য সংশোধন মুছে ফেলা ফাইলগুলি সরান না । যদি আপনার কার্যকারী ট্রিতে অতিরিক্ত ফাইল থাকে যা হেডে নেই, তবে এগুলি অপসারণ করবে না।
git checkout HEAD -- <path>

দ্রষ্টব্য: git checkout --overlay HEAD -- <path>(গিট ২.২২, কিউ ১ 2019) এর সাহায্যে সূচি এবং কার্যক্ষম গাছের মধ্যে উপস্থিত ফাইলগুলি কিন্তু অন্তর্ভুক্ত নয় <tree-ish>, সেগুলি <tree-ish>হুবহু মিলে যায়।

তবে এই চেকআউটটি git update-index --skip-worktree(যে ডিরেক্টরিগুলিকে আপনি অগ্রাহ্য করতে চান) তাকে সম্মান করতে পারে, যেমন " বর্জনিত ফাইলগুলি আমার গিট বিচ্ছিন্ন চেকআউটটিতে পুনরায় প্রদর্শিত হয় কেন? "।


1
পরিষ্কার করে বলো. এর পরে git checkout HEAD -- ., বিচ্ছিন্ন চেকআউট দ্বারা বাদ দেওয়া ফাইলগুলি আবার উপস্থিত হবে। কী git update-index --skip-worktreeকরার কথা?
krlMLr

: @krlmlr লাফালাফি-worktree বা অনুমান-অপরিবর্তিত সূচক একটি এন্ট্রি "অদৃশ্য" Git জন্য চেষ্টা করা দুটি উপায় fallengamer.livejournal.com/93321.html , stackoverflow.com/q/13630849/6309 এবং Stackoverflow। com / এ / 6139470/6309
ভোনসি

@ কেআরএলএমএল এই লিঙ্কগুলি কেবলমাত্র চেষ্টা করার জন্য আপনার পয়েন্টার এবং এটি দেখুন যে কোনও চেকআউট যদি এখনও সেগুলিকে 'স্কিপড-ওয়ার্ক্রিট্রি' হিসাবে চিহ্নিত করা হয় তবে সেই প্রবেশগুলি পুনরুদ্ধার করবে কিনা।
ভনসি

দুঃখিত, কিন্তু হাতের কাজটির জন্য এটি খুব জটিল। আমি একটি ইনক্লুসিভ রিসেট চাই, একচেটিয়া নয়। গিটে এটি করার সত্যিই কোনও ভাল উপায় নেই?
krlMLr

@krlmlr নং: সর্বোত্তম কাজটি করা git checkout HEAD -- <path>, এবং তারপরে পুনরুদ্ধার করা ডিরেক্টরিগুলি মুছুন (তবে যা এখনও স্পার্স চেকআউটে ঘোষণা করা হয়েছে)।
ভনসি

125

গীট বিকাশকারী ডুয়ে নগুয়েনের মতে যিনি দয়া করে বৈশিষ্ট্যটি এবং একটি সামঞ্জস্যতা স্যুইচটি প্রয়োগ করেছেন , নিম্নলিখিতটি গিট ১.৮.৩ হিসাবে প্রত্যাশা অনুযায়ী কাজ করে :

git checkout -- a

( aআপনি যে ডিরেক্টরিটি পুনরায় সেট করতে চান সেটি হ'ল)। আসল আচরণের মাধ্যমে অ্যাক্সেস করা যায়

git checkout --ignore-skip-worktree-bits -- a

5
গিট উন্নয়ন দলের সাথে আপনার প্রচেষ্টাটির জন্য ধন্যবাদ, ফলস্বরূপ গিতে এই পরিবর্তনটির ফলে।
ড্যান ক্রুজ

13
এবং নোট করুন যে এই ক্ষেত্রে "ক" এর অর্থ আপনি যে ডিরেক্টরিটি ফিরিয়ে দিতে চান তা তাই আপনি যদি সেই ডিরেক্টরিটিতে ফিরে যেতে চান তবে কমান্ডটি git checkout -- .সেখানে হওয়া উচিত যেখানে .বর্তমান ডিরেক্টরিটি বোঝায়।
দ্য ওয়েস্টটাইজ ...

5
আমার পক্ষ থেকে একটি মন্তব্য হ'ল আপনাকে অবশ্যই প্রথমে ফোল্ডারটি আনস্টেজ করতে হবে git reset -- a(যেখানে আপনি যে ডিরেক্টরিটি পুনরায় সেট করতে চান সেখানে)
বায়ান

আপনি কি git reset --hardপুরো রেপো চাইলে তাও কি সত্য নয় ?
krlMLr

এবং যদি আপনি সেই ডিরেক্টরিতে কোনও নতুন ফাইল যুক্ত করেন তবে rm -rf aআগে করুন।
টোবিয়াস

30

পরিবর্তনের চেষ্টা করুন

git checkout -- a

প্রতি

git checkout -- `git ls-files -m -- a`

সংস্করণ ১..0.০ থেকে, গিটের স্কিপ-ওয়ার্ক্রিট পতাকাটি সম্মানিতls-files

(কিছু সামান্য বদলান পরিবর্তন আপনার পরীক্ষার স্ক্রিপ্ট চালাতে git commit... করতে git commit -qএবং git statusকরতে git status --shortআউটপুট):

Initialized empty Git repository in /home/user/repo/.git/
After read-tree:
a/a/aa
a/b/ab
b/a/ba
After modifying:
b/a/ba
 D a/a/aa
 D a/b/ab
 M b/a/ba
After checkout:
 M b/a/ba
a/a/aa
a/c/ac
a/b/ab
b/a/ba

প্রস্তাবিত checkoutপরিবর্তনের আউটপুটগুলির সাথে আপনার পরীক্ষার স্ক্রিপ্টটি চালানো হচ্ছে :

Initialized empty Git repository in /home/user/repo/.git/
After read-tree:
a/a/aa
a/b/ab
b/a/ba
After modifying:
b/a/ba
 D a/a/aa
 D a/b/ab
 M b/a/ba
After checkout:
 M b/a/ba
a/a/aa
a/b/ab
b/a/ba

ভাল লাগছে। তবে git checkout"স্কিপ-ওয়ার্ক্রিট্রি" বিটটিকে প্রথমে সম্মান করা উচিত নয় ?
krlmlr

একটি দ্রুত পর্যালোচনা checkout.cএবং tree.cএড়িয়ে যায় না যে স্কিপ-ওয়ার্কট্রি পতাকা ব্যবহৃত হয়েছিল।
ড্যান ক্রুজ

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

18

কেবল পরিবর্তনগুলি বর্জন করার ক্ষেত্রে, অন্যান্য উত্তরের প্রস্তাবিত আদেশ git checkout -- path/বা git checkout HEAD -- path/আদেশগুলি দুর্দান্ত কাজ করে। যাইহোক, আপনি যখন কোনও ডিরেক্টরিকে HEAD ব্যতীত অন্য কোন সংশোধনীতে পুনরায় সেট করতে চান, তখন সেই সমাধানটির একটি উল্লেখযোগ্য সমস্যা থাকে: এটি লক্ষ্য সংশোধনে মুছে ফেলা ফাইলগুলিকে সরিয়ে দেয় না।

সুতরাং পরিবর্তে, আমি নিম্নলিখিত কমান্ডটি ব্যবহার শুরু করেছি:

git diff --cached commit -- subdir | git apply -R --index

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

যেহেতু এই কমান্ডটি বেশ দীর্ঘ এবং আমি এটি প্রায়শই ব্যবহার করার পরিকল্পনা করি, আমি এর জন্য একটি নাম রাখলাম যার নাম রেখেছি reset-checkout:

git config --global alias.reset-checkout '!f() { git diff --cached "$@" | git apply -R --index; }; f'

আপনি এটি এর মতো ব্যবহার করতে পারেন:

git reset-checkout 451a9a4 -- path/to/directory

বা শুধু:

git reset-checkout 451a9a4

আমি গতকাল আপনার মন্তব্য দেখেছি এবং আজ এটি পরীক্ষা করে দেখেছি। আপনার উপন্যাস সহায়ক। +1
ভোনসি

এই git checkout --overlay HEAD -- <path>উত্তরটি কীভাবে @ ভনসি তার উত্তরে উল্লিখিত আদেশের সাথে তুলনা করে ?
এহতেশ চৌধুরী চৌধুরী 21

1
@ এহতেশচৌধুরী নোট যা git checkout --overlay HEAD -- <path>এখনও প্রকাশিত হয়নি (গিট 2.22 Q2 2019 এ প্রকাশিত হবে)
ভোনসি

5

আমি এখানে একটি ভয়াবহ বিকল্প প্রস্তাব দিচ্ছি, যেহেতু গিট ছাড়া কীভাবে কীভাবে করা যায় তার আমার কোনও ধারণা নেই add commitএবং pushএখানে আমি কীভাবে একটি উপ-ডিরেক্টরিকে "রিভার্ট" করেছি:

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


4

একটি রিসেটটি সাধারণত সব কিছু পরিবর্তন করে তবে git stashআপনি যা রাখতে চান তা চয়ন করতে আপনি ব্যবহার করতে পারেন । যেমনটি আপনি উল্লেখ করেছেন, stashসরাসরি কোনও পাথ গ্রহণ করে না, তবে এটি এখনও --keep-indexপতাকা সহ একটি নির্দিষ্ট পাথ রাখতে ব্যবহৃত হতে পারে । আপনার উদাহরণে, আপনি বি ডিরেক্টরিটি স্ট্যাশ করবেন, তারপরে সমস্ত কিছু পুনরায় সেট করুন।

# How to make files a/* reappear without changing b and without recreating a/c?
git add b               #add the directory you want to keep
git stash --keep-index  #stash anything that isn't added
git reset               #unstage the b directory
git stash drop          #clean up the stash (optional)

এটি আপনাকে এমন বিন্দুতে নিয়ে যায় যেখানে আপনার স্ক্রিপ্টের শেষ অংশটি এটি আউটপুট দেবে:

After checkout:
# On branch master
# Changes not staged for commit:
#
#   modified:   b/a/ba
#
no changes added to commit (use "git add" and/or "git commit -a")
a/a/aa
a/b/ab
b/a/ba

আমি বিশ্বাস করি এটিই টার্গেট ফলাফল ছিল (বি পরিবর্তিত থাকবে, একটি / * ফাইল ফিরে এসেছে, একটি / সি পুনরায় তৈরি করা হয়নি)।

এই পদ্ধতির খুব নমনীয় হওয়ার অতিরিক্ত সুবিধা রয়েছে; আপনি ডিরেক্টরিতে যেমন নির্দিষ্ট ফাইল যুক্ত করতে চান তেমন সূক্ষ্ম-জঞ্জাল পেতে পারেন তবে অন্যটি নয় not


এটি দুর্দান্ত, তবে আমার কাছে git addসবকিছুই aঠিক আছে, তাই না? অনুশীলনে কঠিন মনে হচ্ছে।
krlmlr

1
@krlmlr সত্যিই না। git add .তারপরে git reset aআপনি বাদে সমস্ত কিছু যুক্ত করতে পারেন a
জোনাথন

1
@krlmlr এছাড়াও, git addমুছে ফেলা ফাইলগুলি যুক্ত করে না তা লক্ষ করার মতো। সুতরাং, আপনি যদি কেবল মুছে ফেলা ফাইলগুলি পুনরুদ্ধার করে থাকেন git add .তবে সমস্ত পরিবর্তিত ফাইল যুক্ত করবেন তবে মুছে ফেলা ফাইলগুলি নয়।
জোনাথন

3

যদি উপ-ডিরেক্টরিটির আকারটি বিশেষত বিশাল না হয় এবং আপনি সিএলআই থেকে দূরে থাকতে চান, সাব-ডিরেক্টরিটিকে ম্যানুয়ালি পুনরায় সেট করার একটি দ্রুত সমাধান এখানে :

  1. মাস্টার শাখায় স্যুইচ করুন এবং রিসেট হতে সাব-ডিরেক্টরিটি অনুলিপি করুন।
  2. এখন আপনার বৈশিষ্ট্য শাখায় ফিরে যান এবং 1 টি পদক্ষেপে সদ্য তৈরি করা অনুলিপি সহ উপ-ডিরেক্টরিটি প্রতিস্থাপন করুন।
  3. পরিবর্তনগুলি প্রতিশ্রুতিবদ্ধ।

চিয়ার্স। আপনি কেবল নিজের বৈশিষ্ট্য শাখায় একটি উপ-ডিরেক্টরি পুনরায় সেট করে মাস্টার শাখার মতো হতে পারেন !!


আমি এই উত্তরের জন্য কোনও ভোট দেখিনি, তবে কখনও কখনও এটি সাফল্যের সবচেয়ে সহজ গ্যারান্টিযুক্ত পথ।
মামলা

1

আজেদী 32 এর উত্তর আমি যা খুঁজছিলাম তা হ'ল তবে কিছু কমিটের জন্য আমি এই ত্রুটির মধ্যে পড়েছিলাম:

error: cannot apply binary patch to 'path/to/directory' without full index line

ডিরেক্টরিটির কিছু ফাইল বাইনারি ফাইল হওয়ার কারণ হতে পারে। গিট ডিফ কমান্ডে '--binary' বিকল্প যুক্ত করা এটি স্থির করে:

git diff --binary --cached commit -- path/to/directory | git apply -R --index

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.