পৃথক গিট সংগ্রহস্থলে আলাদা (সরানো) উপ-ডিরেক্টরি


1758

আমার একটি গিট সংগ্রহস্থল রয়েছে যার মধ্যে বেশ কয়েকটি উপ-ডিরেক্টরি রয়েছে। এখন আমি দেখতে পেয়েছি যে উপ-ডিরেক্টরিগুলির একটির অপরটির সাথে সম্পর্কিত নয় এবং পৃথক সংগ্রহস্থলে আলাদা করা উচিত।

সাবডিরেক্টরির মধ্যে থাকা ফাইলগুলির ইতিহাস রাখার সময় আমি কীভাবে এটি করতে পারি?

আমি অনুমান করি যে আমি একটি ক্লোন তৈরি করতে এবং প্রতিটি ক্লোনটির অযাচিত অংশগুলি সরিয়ে ফেলতে পারি, তবে আমি মনে করি কোনও পুরানো সংশোধন ইত্যাদি পরীক্ষা করার সময় এটি আমাকে পুরো গাছটি দেবে etc. এটি গ্রহণযোগ্য হতে পারে তবে আমি এই ভান করতে সক্ষম হতে পছন্দ করব দুটি সংগ্রহস্থলের একটি ভাগ করা ইতিহাস নেই।

কেবল এটি পরিষ্কার করতে, আমার নিম্নলিখিত কাঠামো রয়েছে:

XYZ/
    .git/
    XY1/
    ABC/
    XY2/

তবে আমি এটির পরিবর্তে চাই:

XYZ/
    .git/
    XY1/
    XY2/
ABC/
    .git/
    ABC/

7
git filter-branchআমার উত্তর নীচে দেখুন এখন এটি তুচ্ছ ।
jeremyjjbrown

8
@Jermyjjbrown ঠিক আছে। এটি করা আর কঠিন নয় তবে গুগলে সঠিক উত্তর খুঁজে পাওয়া কঠিন কারণ সমস্ত পুরানো উত্তর ফলাফলগুলিতে প্রভাব ফেলে।
অগ্নেল কুরিয়ান

উত্তর:


1228

আপডেট : এই প্রক্রিয়াটি এতটাই সাধারণ, যে গিট দলটি একটি নতুন সরঞ্জাম দিয়ে এটি আরও সহজ করে তুলেছে git subtree,। এখানে দেখুন: পৃথক গিট সংগ্রহস্থলে আলাদা (সরানো) উপ-ডিরেক্টরি


আপনি আপনার সংগ্রহস্থলটিকে ক্লোন করতে চান এবং তারপরে git filter-branchআপনার নতুন রেপোতে যে সাব-ডাইরেক্টরিটি চান তা আপনার আবর্জনা-সংগ্রহের জন্য চিহ্নিত করতে ব্যবহার করতে চান।

  1. আপনার স্থানীয় সংগ্রহস্থলটিকে ক্লোন করতে:

    git clone /XYZ /ABC
    

    (দ্রষ্টব্য: হার্ড-লিঙ্কগুলি ব্যবহার করে ভান্ডারটি ক্লোন করা হবে, তবে এটি কোনও সমস্যা নয় কারণ হার্ড-লিঙ্কযুক্ত ফাইলগুলি নিজের মধ্যে সংশোধিত হবে না - নতুন তৈরি হবে))

  2. এখন আসুন আমরা সেই আকর্ষণীয় শাখাগুলি সংরক্ষণ করি যা আমরা আবারও লিখতে চাই এবং তারপরে সেখানে ঠেলাঠেলি এড়াতে এবং পুরানো প্রতিশ্রুতিগুলি উত্স অনুসারে উল্লেখ করা হবে না তা নিশ্চিত করতে উত্সটি সরিয়ে ফেলুন:

    cd /ABC
    for i in branch1 br2 br3; do git branch -t $i origin/$i; done
    git remote rm origin
    

    বা সমস্ত প্রত্যন্ত শাখার জন্য:

    cd /ABC
    for i in $(git branch -r | sed "s/.*origin\///"); do git branch -t $i origin/$i; done
    git remote rm origin
    
  3. এখন আপনি এমন ট্যাগগুলিও মুছে ফেলতে চাইতে পারেন যার সাবপ্রজেক্টের সাথে কোনও সম্পর্ক নেই; আপনি এটি পরেও করতে পারেন, তবে আপনাকে আবার আপনার রেপো ছাঁটাই করতে হতে পারে। আমি এটি না করে WARNING: Ref 'refs/tags/v0.1' is unchangedসমস্ত ট্যাগের জন্য একটি পেয়েছি (যেহেতু তারা সকলেই সাবপ্রজেক্টের সাথে সম্পর্কিত নয়); তদুপরি, এই জাতীয় ট্যাগগুলি সরানোর পরে আরও স্থান পুনরুদ্ধার করা হবে। স্পষ্টতই git filter-branchঅন্যান্য ট্যাগগুলি আবার লিখতে সক্ষম হওয়া উচিত, তবে আমি এটি যাচাই করতে পারিনি। আপনি যদি সমস্ত ট্যাগ মুছে ফেলতে চান তবে ব্যবহার করুন git tag -l | xargs git tag -d

  4. তারপরে ফিল্টার-শাখা ব্যবহার করুন এবং অন্যান্য ফাইলগুলি বাদ দিতে পুনরায় সেট করুন, যাতে সেগুলি ছাঁটাই করা যায়। আসুন --tag-name-filter cat --prune-emptyখালি কমিটগুলি সরিয়ে ফেলার জন্য এবং ট্যাগগুলি পুনরায় লেখার জন্য যুক্ত করুন (মনে রাখবেন এটির তাদের স্বাক্ষরটি কেড়ে নিতে হবে):

    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC -- --all
    

    বা বিকল্পভাবে, কেবলমাত্র হেড শাখাটি পুনরায় লিখতে এবং ট্যাগ এবং অন্যান্য শাখাগুলি উপেক্ষা:

    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC HEAD
    
  5. তারপরে ব্যাকআপ রিফ্লাগগুলি মুছুন যাতে স্থানটি সত্যই পুনরুদ্ধার করা যায় (যদিও এখন অপারেশন ধ্বংসাত্মক)

    git reset --hard
    git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
    git reflog expire --expire=now --all
    git gc --aggressive --prune=now
    

    এবং এখন আপনার কাছে সমস্ত ইতিহাস সংরক্ষণের সাথে এবিসি সাব ডিরেক্টরি-র একটি স্থানীয় গিট সংগ্রহস্থল রয়েছে।

দ্রষ্টব্য: বেশিরভাগ ব্যবহারের জন্য git filter-branchঅবশ্যই যুক্ত হওয়া প্যারামিটার থাকা উচিত -- --all। হ্যাঁ আসলেই --space-- all। কমান্ডের জন্য এটি সর্বশেষ পরামিতি হওয়া দরকার। মাতলি যেমন আবিষ্কার করেছেন, এটি প্রকল্পের শাখা এবং ট্যাগগুলিকে নতুন রেপোতে অন্তর্ভুক্ত রাখে।

সম্পাদনা করুন: নীচের মন্তব্যগুলির বিভিন্ন পরামর্শগুলি নিশ্চিত করার জন্য সংযুক্ত করা হয়েছিল, উদাহরণস্বরূপ, সংগ্রহস্থলটি আসলে সঙ্কুচিত হয়েছে (যা আগে আগে ছিল না)।


29
খুব ভাল উত্তর। ধন্যবাদ! এবং আমি যা চাইছিলাম তা পেতে, আমি ফিল্টার-শাখা কমান্ডটিতে "- সমস্ত" যুক্ত করেছি।
matli

12
তোমার দরকার কেন --no-hardlinks? একটি হার্ডলিঙ্ক অপসারণ করা অন্য ফাইলকে প্রভাবিত করবে না। গিট অবজেক্টগুলিও অপরিবর্তনীয়। আপনি যদি কেবল মালিক / ফাইলের অনুমতিগুলি পরিবর্তন করতে চান তবেই --no-hardlinks
vdboor

67
একটি অতিরিক্ত পদক্ষেপ আমি সুপারিশ করব "গিট রিমোট আরএম উত্স"। যদি আমার ভুল না হয় তবে এটি মূল সংগ্রহস্থলটিতে ফিরে যেতে বাধা দেবে।
টম

13
যোগ করার filter-branchজন্য আরেকটি আদেশ হ'ল --prune-emptyএখন-খালি কমিটগুলি সরিয়ে ফেলা।
শেঠ জনসন

8
পলের মতো, আমি আমার নতুন রেপোতে প্রকল্পের ট্যাগগুলি চাইনি, তাই আমি ব্যবহার করিনি -- --all। আমিও দৌড়েছি git remote rm origin, এবং আদেশের git tag -l | xargs git tag -dআগেই git filter-branch। এটি আমার .gitডিরেক্টরিটি 60M থেকে 300 ডলারে সঙ্কুচিত করে । নোট করুন যে আকার হ্রাস পেতে আমার এই দুটি কমান্ড চালানোর প্রয়োজন ছিল।
সালটিক্রেন

1321

সহজ উপায় ™

দেখা যাচ্ছে যে এটি এমন একটি সাধারণ এবং দরকারী অনুশীলন যা গিটের ওভারলর্ডরা এটি সত্যই সহজ করে তুলেছে তবে আপনার কাছে গিট (> = 1.7.11 মে 2012) এর একটি নতুন সংস্করণ থাকতে হবে। সর্বশেষ গিটটি কীভাবে ইনস্টল করতে হয় তার জন্য পরিশিষ্ট দেখুন । এছাড়াও, নীচের ওয়াকথ্রোতে একটি বাস্তব-বিশ্বের উদাহরণ রয়েছে ।

  1. পুরানো রেপো প্রস্তুত

    cd <big-repo>
    git subtree split -P <name-of-folder> -b <name-of-new-branch>
    

    দ্রষ্টব্য: <name-of-folder> অবশ্যই শীর্ষস্থানীয় বা পিছনে অক্ষর থাকা উচিত নয়। উদাহরণস্বরূপ, নামকৃত ফোল্ডারটি subprojectঅবশ্যই পাস করা হবে subproject, না./subproject/

    উইন্ডোজ ব্যবহারকারীদের জন্য নোট: আপনার ফোল্ডারের গভীরতা> 1 এর ক্ষেত্রে <name-of-folder>অবশ্যই * নিক্স স্টাইলের ফোল্ডার বিভাজক (/) থাকতে হবে। উদাহরণস্বরূপ, path1\path2\subprojectMUST নামের ফোল্ডারটি হিসাবে পাস করা উচিতpath1/path2/subproject

  2. নতুন রেপো তৈরি করুন

    mkdir ~/<new-repo> && cd ~/<new-repo>
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. নতুন রেপোকে গিটহাব বা অন্য যে কোনও জায়গায় লিঙ্ক করুন

    git remote add origin <git@github.com:user/new-repo.git>
    git push -u origin master
    
  4. পরিষ্কারের ভিতরে <big-repo>, ইচ্ছা হলে

    git rm -rf <name-of-folder>
    

    দ্রষ্টব্য : এটি সংগ্রহস্থলের সমস্ত .তিহাসিক তথ্যসূত্র রেফার করে। নীচের পরিশিষ্ট দেখুন যদি আপনি সত্যিকার অর্থে পাসওয়ার্ড নিয়ে উদ্বিগ্ন হন বা আপনার .gitফোল্ডারের ফাইলের আকার হ্রাস করতে হবে ।

...

walkthrough

এগুলি উপরের মতো একই পদক্ষেপ , তবে ব্যবহারের পরিবর্তে আমার সংগ্রহশালার জন্য আমার সঠিক পদক্ষেপগুলি অনুসরণ করে <meta-named-things>

নোডে জাভাস্ক্রিপ্ট ব্রাউজার মডিউলগুলি প্রয়োগ করার জন্য আমার এখানে একটি প্রকল্প রয়েছে:

tree ~/node-browser-compat

node-browser-compat
├── ArrayBuffer
├── Audio
├── Blob
├── FormData
├── atob
├── btoa
├── location
└── navigator

আমি একটি একক ফোল্ডারকে btoaআলাদা গিট ভাণ্ডারে বিভক্ত করতে চাই

cd ~/node-browser-compat/
git subtree split -P btoa -b btoa-only

আমার এখন একটি নতুন শাখা রয়েছে, btoa-onlyএটির জন্য কেবল প্রতিশ্রুতি রয়েছে btoaএবং আমি একটি নতুন সংগ্রহশালা তৈরি করতে চাই।

mkdir ~/btoa/ && cd ~/btoa/
git init
git pull ~/node-browser-compat btoa-only

এরপরে আমি গিটহাব বা বিটবকেট, বা যা কিছুতে একটি নতুন রেপো তৈরি করি এবং এটি হিসাবে যুক্ত করি origin

git remote add origin git@github.com:node-browser-compat/btoa.git
git push -u origin master

শুভ দিন!

দ্রষ্টব্য: আপনি যদি একটি সঙ্গে একটি রেপো নির্মিত তাহলে README.md, .gitignoreএবং LICENSE, আপনাকে প্রথমে টান করতে হবে:

git pull origin master
git push origin master

শেষ অবধি, আমি বড় রেপো থেকে ফোল্ডারটি সরাতে চাই

git rm -rf btoa

...

উপাঙ্গ

ম্যাকোজে সর্বশেষ গিট

হোমব্রিউ ব্যবহার করে গিটের সর্বশেষতম সংস্করণটি পেতে :

brew install git

উবুন্টুতে সর্বশেষ গিট

sudo apt-get update
sudo apt-get install git
git --version

যদি এটি কাজ না করে (আপনার কাছে উবুন্টুর একটি খুব পুরানো সংস্করণ রয়েছে), চেষ্টা করুন

sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update
sudo apt-get install git

যদি এটি এখনও কাজ করে না, চেষ্টা করুন

sudo chmod +x /usr/share/doc/git/contrib/subtree/git-subtree.sh
sudo ln -s \
/usr/share/doc/git/contrib/subtree/git-subtree.sh \
/usr/lib/git-core/git-subtree

মন্তব্য থেকে rui.araujo ধন্যবাদ।

আপনার ইতিহাস সাফ করা হচ্ছে

ডিফল্টরূপে গিট থেকে ফাইলগুলি সরানো আসলে সেগুলি সরাবে না, কেবলমাত্র তারা বাধ্য হয় যে তারা আর নেই। আপনি যদি আসলে theতিহাসিক তথ্যসূত্রগুলি মুছতে চান (যেমন আপনার কাছে একটি পাসওয়ার্ড রয়েছে) তবে আপনার এটি করতে হবে:

git filter-branch --prune-empty --tree-filter 'rm -rf <name-of-folder>' HEAD

এর পরে আপনি পরীক্ষা করতে পারেন যে আপনার ফাইল বা ফোল্ডারটি এখন আর গিট ইতিহাসে দেখাবে না

git log -- <name-of-folder> # should show nothing

তবে, আপনি গিটহাব এবং অন্যর মতো মুছে ফেলতে "পুশ" করতে পারবেন না । যদি আপনি চেষ্টা করেন তবে একটি ত্রুটি পাবেন এবং যা করার git pullআগে আপনাকে তা করতে হবে git push- এবং তারপরে আপনি নিজের ইতিহাসে সমস্ত কিছু ফিরে পেয়ে যাবেন ।

সুতরাং আপনি যদি ইতিহাসটি "উত্স" থেকে মুছে ফেলতে চান - যার অর্থ এটি গিটহাব, বিটবুকিট, ইত্যাদি থেকে মুছতে পারে - আপনাকে রেপো মুছতে হবে এবং রেপোর একটি ছাঁটাই অনুলিপিটি আবার চাপ দিতে হবে। তবে অপেক্ষা করুন - আরও আছে ! - আপনি যদি সত্যিই কোনও পাসওয়ার্ড বা এমন কিছু থেকে মুক্তি পাওয়ার বিষয়ে উদ্বিগ্ন হন তবে আপনাকে ব্যাকআপ ছাঁটাই করতে হবে (নীচে দেখুন)।

আরও .gitছোট করা

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

তাই আপনি যদি সত্যিই চাই ট্র্যাশ খালি করার ক্লোন আকার হ্রাস একটি রেপো এর অবিলম্বে আপনার এই সত্যিই অদ্ভুত জিনিস সব করতে হবে:

rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune=now

git reflog expire --all --expire-unreachable=0
git repack -A -d
git prune

এটি বলেছিল, আমি এই পদক্ষেপগুলি সম্পাদন না করার পরামর্শ দিচ্ছি যদি না আপনি জানেন যে আপনার প্রয়োজন - ঠিক যদি আপনি ভুল সাব-ডিরেক্টরিকে ছাঁটাই করে থাকেন, তাই আপনি? আপনি রেপো চাপ দেওয়ার সময় ব্যাকআপ ফাইলগুলি ক্লোন করা উচিত নয়, সেগুলি কেবল আপনার স্থানীয় অনুলিপিটিতে থাকবে।

ধার


16
git subtreeএখনও 'অবদান' ফোল্ডারের অংশ এবং এটি সমস্ত ডিস্ট্রোজে ডিফল্টরূপে ইনস্টল করা হয়নি। github.com/git/git/blob/master/contrib/subtree
পেঁয়াজকে

11
@krlmlr sudo chmod + x /usr/share/doc/git/contrib/subtree/git-subtree.sh sudo ln -s /usr/share/doc/git/contrib/subtree/git-subtree.sh / usr / lib / গিট-কোর / গিট-
সাবট্রি

41
আপনি যদি কোনও পাসওয়ার্ডটিকে পাবলিক ভান্ডারটিতে ঠেলে দেন তবে আপনার পাসওয়ার্ডটি পরিবর্তন করা উচিত, এটি পাবলিক রেপো থেকে সরানোর চেষ্টা করবেন না এবং আশা করি কেউ এটি দেখে নি।
মাইলস রুট

8
এই সমাধানটি ইতিহাস সংরক্ষণ করে না।
সিউর

18
popdএবং pushdকমান্ড এটিকে বরং অন্তর্নিহিত এবং কঠিন grok করার তা করতে ইচ্ছুক কি ...
jones77

133

পল এর উত্তর / এবিসি সমন্বিত একটি নতুন সংগ্রহশালা তৈরি করে, তবে / এক্সওয়াইজেডের মধ্যে / এবিসি সরিয়ে দেয় না। নিম্নলিখিত কমান্ডটি / এক্সবিজেডের মধ্যে থেকে / এবিসি সরিয়ে ফেলবে:

git filter-branch --tree-filter "rm -rf ABC" --prune-empty HEAD

অবশ্যই, এটি প্রথমে একটি 'ক্লোন - নন-হার্ডলিঙ্কস' সংগ্রহস্থলে পরীক্ষা করুন এবং পুনরায় সেট করুন, জিসি এবং প্রুন কমান্ডগুলি পল তালিকা সহ এটি অনুসরণ করুন।


53
এটি তৈরি করুন git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch ABC" --prune-empty HEADএবং এটি আরও দ্রুত হবে। ইনডেক্স-ফিল্টার সূচকে কাজ করে যখন ট্রি-ফিল্টারকে প্রতিটি প্রতিশ্রুতিবদ্ধতার জন্য সমস্ত কিছু চেকআউট এবং মঞ্চস্থ করতে হয়
fmarc

51
কিছু ক্ষেত্রে সংগ্রহস্থলের এক্সওয়াইজেডের ইতিহাসকে বিশৃঙ্খলাবদ্ধ করা ওভারকিল ... কেবল একটি সাধারণ "আরএম-আরএফ এবিসি; গিট আরএম-আর এ বি সি; গিট কমিট-এম'সেক্সট্রেটেড এবিসিকে তার নিজস্ব রেপোতে" "বেশিরভাগ মানুষের পক্ষে আরও ভাল কাজ করতে পারে।
ইভজেনি

2
আপনি সম্ভবত এই কমান্ডটিতে -f (ফোর্স) ব্যবহার করতে চান যদি আপনি এটি একাধিকবার করেন, উদাহরণস্বরূপ, দুটি ডিরেক্টরি পৃথক করার পরে অপসারণ করতে। অন্যথায় আপনি "একটি নতুন ব্যাকআপ তৈরি করতে পারবেন না" পাবেন।
ব্রায়ান কার্লটন

4
আপনি যদি --index-filterপদ্ধতিটি করছেন তবে আপনি এটিও তৈরি করতে চাইতে পারেন git rm -q -r -f, যাতে প্রতিটি অনুরোধ মুছে ফেলা প্রতিটি ফাইলের জন্য একটি লাইন প্রিন্ট না করে।
এরিক ন্যাসেথ

1
আমি পৌলের উত্তর সম্পাদনা করার পরামর্শ দিচ্ছি, কেবলমাত্র পল এর পুরোপুরি বিশদ কারণ।
এরিক অ্যারোনস্টি

96

আমি খুঁজে পেয়েছি যে নতুন সংগ্রহশালা থেকে পুরানো ইতিহাসটি সঠিকভাবে মুছতে গেলে আপনাকে এই filter-branchপদক্ষেপের পরে আরও কিছু কাজ করতে হবে ।

  1. ক্লোন এবং ফিল্টার করুন:

    git clone --no-hardlinks foo bar; cd bar
    git filter-branch --subdirectory-filter subdir/you/want
    
  2. পুরানো ইতিহাসের প্রতিটি রেফারেন্স সরান। "উত্স" আপনার ক্লোনটির উপর নজর রাখছিল এবং ফিল্টার-শাখা পুরানো জিনিসগুলি সংরক্ষণ করে যেখানে "মূল":

    git remote rm origin
    git update-ref -d refs/original/refs/heads/master
    git reflog expire --expire=now --all
    
  3. এখনও, আপনার ইতিহাস এমন একটি প্যাকফাইলে আটকে থাকতে পারে যা fsck স্পর্শ করবে না। এটিকে টুকরো টুকরো করে ফেলুন, একটি নতুন প্যাকফিল তৈরি করুন এবং অব্যবহৃত অবজেক্টগুলি মুছে দিন:

    git repack -ad
    

নেই এই একটি ব্যাখ্যাফিল্টার-শাখা জন্য ম্যানুয়াল


3
আমার মনে হয় কিছুটা মত git gc --aggressive --prune=nowএখনও নিখোঁজ, তাইনা?
অ্যালবার্ট

1
@ অ্যালবার্ট দ্য রিপ্যাক কমান্ড এটি যত্ন করে, এবং কোনও আলগা বস্তু থাকবে না would
জোশ লি

হ্যাঁ, git gc --aggressive --prune=nowঅনেক বেশি রেপো হ্রাস পেয়েছে
টোমেক ওয়েদারকা

সহজ এবং মার্জিত। ধন্যবাদ!
মার্কো পেলেগ্রিনি

40

সম্পাদনা: বাশ স্ক্রিপ্ট যুক্ত হয়েছে।

এখানে দেওয়া উত্তরগুলি আমার জন্য কেবল আংশিকভাবে কাজ করেছে; প্রচুর বড় ফাইল ক্যাশে রয়ে গেছে। অবশেষে কী কাজ করেছে (ফ্রিণোডে # জিটে কয়েক ঘন্টা পরে):

git clone --no-hardlinks file:///SOURCE /tmp/blubb
cd blubb
git filter-branch --subdirectory-filter ./PATH_TO_EXTRACT  --prune-empty --tag-name-filter cat -- --all
git clone file:///tmp/blubb/ /tmp/blooh
cd /tmp/blooh
git reflog expire --expire=now --all
git repack -ad
git gc --prune=now

পূর্ববর্তী সমাধানগুলির সাথে, সংগ্রহস্থলের আকার প্রায় 100 এমবি ছিল। এটি এটিকে 1.7 মেগাবাইটে নামিয়ে আনল। হতে পারে এটি কাউকে সাহায্য করে :)


নিম্নলিখিত বাশ স্ক্রিপ্টটি স্বয়ংক্রিয়ভাবে কাজ করে:

!/bin/bash

if (( $# < 3 ))
then
    echo "Usage:   $0 </path/to/repo/> <directory/to/extract/> <newName>"
    echo
    echo "Example: $0 /Projects/42.git first/answer/ firstAnswer"
    exit 1
fi


clone=/tmp/${3}Clone
newN=/tmp/${3}

git clone --no-hardlinks file://$1 ${clone}
cd ${clone}

git filter-branch --subdirectory-filter $2  --prune-empty --tag-name-filter cat -- --all

git clone file://${clone} ${newN}
cd ${newN}

git reflog expire --expire=now --all
git repack -ad
git gc --prune=now

26

এটি আর জটিল নয় আর আপনি আপনার ক্লোনোর গিটার ফিল্টার-শাখা কমান্ডটি কেবল নিজের ক্লায়েন্টে চান না এমন সাব-ডিরেক্টরিগুলি খালি করতে এবং তারপরে নতুন রিমোটে চাপতে পারেন।

git filter-branch --prune-empty --subdirectory-filter <YOUR_SUBDIR_TO_KEEP> master
git push <MY_NEW_REMOTE_URL> -f .

3
এটা চমত্কার ভাবে কাজ করেছে. উপরের উদাহরণে আপনার সাবস্ক্রিডিটি হ'ল সাব-ডিরেক্টরিটি যা আপনি কেপ রাখতে চান, অন্য সমস্ত কিছুই সরানো হবে
জেটি টেলর

1
আপনার মন্তব্য ভিত্তিক আপডেট।
jeremyjjbrown

2
এটি প্রশ্নের উত্তর দেয় না। দস্তাবেজগুলি থেকে এটি বলে The result will contain that directory (and only that) as its project root.এবং প্রকৃতপক্ষে এটিই আপনি পাবেন, অর্থাত্ মূল প্রকল্প কাঠামো সংরক্ষণ করা হয়নি।
নিকব্রেট

2
@ নিকব্রেট কী কী সমস্যা আছে তা দেখাতে, আপনি কি XYZ এবং ABC- র সাথে প্রশ্নটির মতো আপনার সমস্যাটি চিত্রিত করতে পারেন?
আদম

@jeremyjjbrown এটা ক্লোন রেপো পুনরায় ব্যবহার করার জন্য এবং একটি নতুন রেপো, অর্থাত্ আমার প্রশ্ন এখানে ব্যবহার করবেন সম্ভব stackoverflow.com/questions/49269602/...
Qiulang

19

আপডেট : গিট-সাবট্রি মডিউলটি এতটাই কার্যকর ছিল যে গিট দলটি এটিকে মূল টানে এবং এটি তৈরি করেছে git subtree। এখানে দেখুন: পৃথক গিট সংগ্রহস্থলে আলাদা (সরানো) উপ-ডিরেক্টরি

গিট-সাবট্রি এর জন্য কার্যকর হতে পারে

http://github.com/apenwarr/git-subtree/blob/master/git-subtree.txt (অবমানিত)

http://psionides.jogger.pl/2010/02/04/sharing-code-between-projects-with-git-subtree/


1
গিট-সাবট্রি এখন গিতের অংশ, যদিও এটি অবদানের গাছে রয়েছে তাই সর্বদা ডিফল্টরূপে ইনস্টল করা হয় না। আমি জানি এটি হোমব্রেউ গিট সূত্র দ্বারা ইনস্টল করা আছে তবে এর ম্যান পৃষ্ঠাটি ছাড়াই। অ্যাপেনওয়ার এইভাবে তার সংস্করণটিকে অপ্রচলিত বলে।
ইক্রিস্টোফারসন

19

একাধিক সাব ফোল্ডারকে ( নতুনভাবে বলা যাক এবং ) একটি নতুন গিট রিপোজিটরিতে বিভক্ত করার জন্য এখানে কুলএজে 86 "এর " দ্য ইজি ওয়ে ™ "উত্তরে একটি ছোট্ট পরিবর্তন রয়েছে ।sub1sub2

সহজ উপায় ™ (একাধিক সাব ফোল্ডার)

  1. পুরানো রেপো প্রস্তুত

    pushd <big-repo>
    git filter-branch --tree-filter "mkdir <name-of-folder>; mv <sub1> <sub2> <name-of-folder>/" HEAD
    git subtree split -P <name-of-folder> -b <name-of-new-branch>
    popd
    

    দ্রষ্টব্য: <name-of-folder> অবশ্যই শীর্ষস্থানীয় বা পিছনে অক্ষর থাকা উচিত নয়। উদাহরণস্বরূপ, নামকৃত ফোল্ডারটি subprojectঅবশ্যই পাস করা হবে subproject, না./subproject/

    উইন্ডোজ ব্যবহারকারীদের জন্য দ্রষ্টব্য: আপনার ফোল্ডারের গভীরতা> 1 এর ক্ষেত্রে <name-of-folder>অবশ্যই * নিক্স স্টাইলের ফোল্ডার বিভাজক (/) থাকতে হবে। উদাহরণস্বরূপ, path1\path2\subprojectMUST নামের ফোল্ডারটি হিসাবে পাস করা উচিত path1/path2/subproject। তবুও mvকমান্ড ব্যবহার করবেন না move

    চূড়ান্ত দ্রষ্টব্য: বেস উত্তরের সাথে অনন্য এবং বড় পার্থক্য হ'ল স্ক্রিপ্টের " git filter-branch..." দ্বিতীয় লাইন

  2. নতুন রেপো তৈরি করুন

    mkdir <new-repo>
    pushd <new-repo>
    
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. নতুন রেপোকে গিথুব বা অন্য যে কোনও জায়গায় লিঙ্ক করুন

    git remote add origin <git@github.com:my-user/new-repo.git>
    git push origin -u master
    
  4. পরিষ্কার করা, যদি ইচ্ছা হয়

    popd # get out of <new-repo>
    pushd <big-repo>
    
    git rm -rf <name-of-folder>
    

    দ্রষ্টব্য : এটি সংগ্রহস্থলের সমস্ত .তিহাসিক রেফারেন্স ছেড়ে দেয়। আপনি যদি পাসওয়ার্ড দেওয়ার বিষয়ে সত্যই উদ্বিগ্ন থাকেন বা আপনার .gitফোল্ডারের ফাইলের আকার হ্রাস করতে হয় তবে মূল উত্তরে পরিশিষ্ট দেখুন


1
এটি আমার জন্য সামান্য পরিবর্তন নিয়ে কাজ করেছিল। কারণ আমার sub1এবং sub2ফোল্ডারগুলি প্রাথমিক সংস্করণের সাথে উপস্থিত করেনি, আমি আমার পরিবর্তন করতে ছিল --tree-filterনিম্নরূপ স্ক্রিপ্ট: "mkdir <name-of-folder>; if [ -d sub1 ]; then mv <sub1> <name-of-folder>/; fi"। দ্বিতীয় filter-branchকমান্ডের জন্য আমি <sub1> কে <sub2>, <name-of-folder> এর বাদ দেওয়া সৃষ্টি দিয়ে প্রতিস্থাপন করেছি এবং বিদ্যমান ব্যাকআপের সতর্কতা ওভাররাইড করার -fপরে অন্তর্ভুক্ত করেছি filter-branch
প্লাগেন

ইতিহাসের সময়ে কোনও সাবডিয়ার বদলেছে কিনা এটি কাজ করে না। কিভাবে এই সমাধান করা যেতে পারে?
নাইট্রাস

@ নিউট্রাসরা রজারডপ্যাকের উত্তর দেখে। এই অন্যান্য উত্তরের সমস্ত তথ্য পড়ার এবং শোষণ করার পরে এটি খুঁজে পেতে আমাকে কিছুটা সময় নিয়েছে।
আদম

12

মূল প্রশ্নটি চায় যে এক্সওয়াইজেড / এবিসি / (* ফাইলগুলি) এবিসি / এবিসি / (* ফাইল) হয়ে উঠুক। আমার নিজের কোডের জন্য গৃহীত উত্তরটি প্রয়োগ করার পরে, আমি লক্ষ্য করেছি যে এটি আসলে এক্সওয়াইজেড / এবিসি / (* ফাইল )গুলিকে এবিসি / (* ফাইল) এ পরিবর্তন করে। ফিল্টার-শাখার ম্যান পৃষ্ঠা এমনকি বলে,

ফলাফলটিতে তার প্রকল্পের মূল হিসাবে সেই ডিরেক্টরিটি (এবং কেবলমাত্র) থাকবে "

অন্য কথায়, এটি শীর্ষ স্তরের ফোল্ডারটিকে একটি স্তর "আপ" করে তোলে। এটি একটি গুরুত্বপূর্ণ পার্থক্য কারণ, উদাহরণস্বরূপ, আমার ইতিহাসে আমি একটি শীর্ষ স্তরের ফোল্ডারটির নামকরণ করেছি। ফোল্ডারগুলিকে এক পর্যায়ে উন্নীত করে, গিট প্রতিশ্রুতিতে যেখানে আমি নাম পরিবর্তন করেছি তাতে ধারাবাহিকতা হারায়।

ফিল্টার-ব্রাঞ্চের পরে আমি কনস্টিটিউটি হারিয়েছি

তারপরে প্রশ্নের আমার উত্তরটি হ'ল সংগ্রহশালার 2 টি অনুলিপি তৈরি করতে হবে এবং আপনি প্রতিটি ফোল্ডার (গুলি) ম্যানুয়ালি মুছে ফেলতে চান each এই পৃষ্ঠাটি আমার সাথে এটি সমর্থন করে:

[...] যদি এই সমস্যাটি সমাধান করার জন্য একটি সাধারণ একক প্রতিশ্রুতি যথেষ্ট হয় তবে [এই আদেশটি] ব্যবহার এড়িয়ে চলুন


1
আমি সেই গ্রাফের স্টাইলটি পছন্দ করি। আপনি জিজ্ঞাসা করতে পারেন আপনি কোন সরঞ্জাম ব্যবহার করছেন?
স্লিপ ডি থম্পসন

3
ম্যাকের জন্য টাওয়ার আমি সত্যিই এটা পছন্দ করি. এটি নিজের জন্য ম্যাকে স্যুইচ করা প্রায় মূল্যবান।
এমএম

2
হ্যাঁ, যদিও আমার ক্ষেত্রে, আমার সাব-ফোল্ডারটির targetdirকোনও এক সময় নাম বদলে দেওয়া হয়েছিল এবং git filter-branchকেবলমাত্র একটি দিন বলা হয়েছিল , নামটি পূর্বে করা সমস্ত প্রতিশ্রুতি মুছে ফেলা! চিত্তাকর্ষক, গিট কতটা পারদর্শী তা বিবেচনা করে এমন জিনিসগুলি এমনকি ব্যক্তিগত সামগ্রীর খণ্ডগুলির স্থানান্তর করতেও পারদর্শী!
জে অ্যালেন

1
ওহ, এছাড়াও, যদি কেউ একই নৌকায় নিজেকে খুঁজে পান তবে আমি যে আদেশটি ব্যবহার করেছি তা এখানে। ভুলে যাবেন না যে git rmএকাধিক আরগ নেয়, তাই এটি প্রতিটি ফাইল / ফোল্ডারের জন্য চালানোর কোনও কারণ নেই: BYEBYE="dir/subdir2 dir2 file1 dir/file2"; git filter-branch -f --index-filter "git rm -q -r -f --cached --ignore-unmatch $BYEBYE" --prune-empty -- --all
জে অ্যালেন

7

পলের উত্তরে যুক্ত করতে আমি জানতে পেরেছিলাম যে অবশেষে স্থানটি পুনরুদ্ধার করতে, আমাকে একটি পরিষ্কার ভান্ডারটিতে হেড ঠেকাতে হবে এবং এটি .git / অবজেক্টস / প্যাক ডিরেক্টরিটির আকারকে ছাঁটাবে।

অর্থাত

$ এমকেডির ... এবিসি.git
$ সিডি ... এবিসি.git
it গিট থ্রি - ব্যারে

জিসি ছাঁটাইয়ের পরে, এছাড়াও করুন:

it গিট ধাক্কা ... ABC.git হেড

তাহলে আপনি করতে পারেন

it গিট ক্লোন ... ABC.git

এবং এবিসি / .git এর আকার হ্রাস পেয়েছে

প্রকৃতপক্ষে, কিছু সময় সাপেক্ষ পদক্ষেপের (যেমন গিট জিসি) সংগ্রহস্থল পরিষ্কার করার ধরণের সাথে প্রয়োজন হয় না, যেমন:

it গিট ক্লোন - না-হার্ডলিঙ্ক / এক্সওয়াইজেড / এবিসি
it গিট ফিল্টার-শাখা - সাবডিরেক্টরি-ফিল্টার এবিসি হেড
it গিট রিসেট --হার্ড
it গিট ধাক্কা ... ABC.git হেড

6

সঠিক উপায় এখন নিম্নলিখিত:

git filter-branch --prune-empty --subdirectory-filter FOLDER_NAME [first_branch] [another_branch]

গিটহাবের কাছে এখন এই জাতীয় কেস সম্পর্কে ছোট্ট নিবন্ধও রয়েছে ।

তবে আপনার অরিজিনাল রেপোটিকে প্রথমে পৃথক ডিরেক্টরিতে ক্লোন করতে ভুলবেন না (কারণ এটি সমস্ত ফাইল এবং অন্যান্য ডিরেক্টরি মুছে ফেলবে এবং তাদের সাথে আপনার কাজ করার সম্ভাবনা রয়েছে)।

সুতরাং আপনার অ্যালগরিদমটি হওয়া উচিত:

  1. আপনার দূরবর্তী রেপো অন্য ডিরেক্টরিতে ক্লোন করুন
  2. git filter-branchকিছু উপ-ডিরেক্টরিতে কেবল বাম ফাইল ব্যবহার করে নতুন রিমোটে চাপ দিন new
  3. আপনার মূল রিমোট রেপো থেকে এই উপ-ডিরেক্টরি সরানোর প্রতিশ্রুতিবদ্ধ করুন

6

এটি প্রদর্শিত হয় যে এখানে বেশিরভাগ (সমস্ত?) উত্তরগুলি কোনও না কোনও রূপ git filter-branch --subdirectory-filterএবং এর জাতীয়তার উপর নির্ভর করে । এটি বেশিরভাগ ক্ষেত্রে "বেশিরভাগ সময়" কাজ করতে পারে, উদাহরণস্বরূপ আপনি যখন ফোল্ডারটির নাম পরিবর্তন করেছেন, উদাহরণস্বরূপ:

 ABC/
    /move_this_dir # did some work here, then renamed it to

ABC/
    /move_this_dir_renamed

যদি আপনি "মুভি_ম_নামেমেড" নিষ্কাশন করতে একটি সাধারণ গিট ফিল্টার স্টাইল করেন তবে আপনি প্রাথমিকভাবে মুভি_সিস_ডির ( রেফ ) থাকাকালীন পেছন থেকে ঘটে যাওয়া ফাইল পরিবর্তন ইতিহাস হারাবেন ।

এইভাবে দেখা যাচ্ছে যে সমস্ত পরিবর্তনের ইতিহাসকে সত্যই রাখার একমাত্র উপায় (যদি আপনার ক্ষেত্রে এরকম হয়), মূলত, সংগ্রহস্থলটি অনুলিপি করা (একটি নতুন রেপো তৈরি করা, এটির উত্স হিসাবে সেট করুন), তারপরে অন্য সব কিছুকে নাক করে দিন এবং পিতা-মাতার কাছে উপ-ডিরেক্টরিটির নাম বদলে দিন:

  1. স্থানীয়ভাবে মাল্টি-মডিউল প্রকল্পটি ক্লোন করুন
  2. শাখা - সেখানে কি আছে তা পরীক্ষা করুন: git branch -a
  3. আপনার ওয়ার্কস্টেশনে স্থানীয় অনুলিপি পেতে বিভাগে অন্তর্ভুক্ত করার জন্য প্রতিটি শাখায় একটি চেকআউট করুন: git checkout --track origin/branchABC
  4. একটি নতুন ডিরেক্টরিতে একটি অনুলিপি তৈরি করুন: cp -r oldmultimod simple
  5. নতুন প্রকল্পের অনুলিপিটিতে যান: cd simple
  6. এই প্রকল্পে প্রয়োজন হয় না এমন অন্যান্য মডিউলগুলি থেকে মুক্তি পান:
  7. git rm otherModule1 other2 other3
  8. এখন লক্ষ্য মডিউলের কেবলমাত্র সাবডির বাকি
  9. মডিউল সাবডির থেকে মুক্তি পান যাতে মডিউল রুটটি নতুন প্রকল্পের মূল হয়ে যায়
  10. git mv moduleSubdir1/* .
  11. রিলিক সাবডির মুছুন: rmdir moduleSubdir1
  12. যে কোনও সময়ে পরিবর্তনগুলি পরীক্ষা করুন: git status
  13. নতুন গিট রেপো তৈরি করুন এবং এতে এই প্রকল্পটি দেখানোর জন্য এটির URL টি অনুলিপি করুন:
  14. git remote set-url origin http://mygithost:8080/git/our-splitted-module-repo
  15. এটি ভাল যাচাই করুন: git remote -v
  16. দূরবর্তী রেপো পর্যন্ত পরিবর্তনগুলি পুশ করুন: git push
  17. রিমোট রেপোতে যান এবং এটি সমস্ত সেখানে যাচাই করুন
  18. প্রয়োজনীয় অন্য যে কোনও শাখার জন্য এটি পুনরাবৃত্তি করুন: git checkout branch2

এটি গিথুব ডকটির অনুসরণ করে "একটি নতুন ফোল্ডারে একটি সাবফোল্ডার বিভক্ত করা" মডিউলটিকে নতুন রেপোতে ঠেলে দেওয়ার জন্য 6-10 পদক্ষেপ।

এটি আপনাকে .git ফোল্ডারে কোনও স্থান সাশ্রয় করবে না, তবে এটি ফাইলগুলির জন্য আপনার পুনর্নবীকরণগুলি জুড়ে আপনার সমস্ত পরিবর্তন ইতিহাস সংরক্ষণ করবে। ইতিহাসের "প্রচুর পরিমাণ" না হারাতে এগুলি মূল্যহীন হতে পারে ইত্যাদি But তবে কমপক্ষে আপনাকে পুরানো প্রতিশ্রুতি না হারানোর নিশ্চয়তা দেওয়া হচ্ছে!


1
গিট খড়ের ছিটে সুই পেয়েছি! এখন আমি আমার সমস্ত প্রতিশ্রুতিবদ্ধ ইতিহাস রাখতে পারি।
আদম

5

সাবফোল্ডারগুলিকে নতুন ভাণ্ডারে বিভক্ত করার জন্য আমি গিটহাবের গাইডের পরামর্শ দিচ্ছি । পদক্ষেপগুলি পৌলের উত্তরের সমান , তবে আমি তাদের নির্দেশাবলী বুঝতে আরও সহজ পেয়েছি।

আমি নির্দেশাবলী পরিবর্তন করেছি যাতে তারা গিটহাবের হোস্ট করা না হয়ে স্থানীয় সংগ্রহস্থলের জন্য আবেদন করতে পারে।


একটি সাবফোল্ডারকে নতুন ভাণ্ডারে বিভক্ত করা

  1. ওপেন গিট ব্যাশ

  2. আপনার নতুন সংগ্রহস্থলটি যেখানে তৈরি করতে চান সেখানে বর্তমান ওয়ার্কিং ডিরেক্টরিটি পরিবর্তন করুন।

  3. সাবফোল্ডার ধারণ করে এমন সংগ্রহস্থলটি ক্লোন করুন।

git clone OLD-REPOSITORY-FOLDER NEW-REPOSITORY-FOLDER
  1. আপনার চলমান ডিরেক্টরিটি আপনার ক্লোন করা ভাণ্ডারগুলিতে পরিবর্তন করুন।

cd REPOSITORY-NAME
  1. সংগ্রহস্থলের বাকি ফাইলগুলি থেকে সাবফোল্ডারটি ফিল্টার করতে git filter-branch, এই তথ্য সরবরাহ করে চালান :
    • FOLDER-NAME: আপনার প্রকল্পের মধ্যে যে ফোল্ডারটি থেকে আপনি আলাদা একটি সংগ্রহশালা তৈরি করতে চান।
      • পরামর্শ: উইন্ডোজ ব্যবহারকারীদের /ফোল্ডারগুলি সীমিত করতে ব্যবহার করা উচিত ।
    • BRANCH-NAME: আপনার বর্তমান প্রকল্পের জন্য ডিফল্ট শাখা, উদাহরণস্বরূপ, masterবা gh-pages

git filter-branch --prune-empty --subdirectory-filter FOLDER-NAME  BRANCH-NAME 
# Filter the specified branch in your directory and remove empty commits
Rewrite 48dc599c80e20527ed902928085e7861e6b3cbe6 (89/89)
Ref 'refs/heads/BRANCH-NAME' was rewritten

ভাল পোস্ট, তবে আমি আপনার লিঙ্কিত ডকটির প্রথম অনুচ্ছেদটি লক্ষ্য করেছি তবে If you create a new clone of the repository, you won't lose any of your Git history or changes when you split a folder into a separate repository.এখনও এখানে সমস্ত উত্তর সম্পর্কে মন্তব্য অনুসারে filter-branchএবং subtreeস্ক্রিপ্টের ফলে ইতিহাসের ক্ষতি হয় যেখানেই কোনও উপ-ডিরেক্টরিটির নতুন নামকরণ করা হয়েছে। এর সমাধানের জন্য কি কিছু করা যায়?
আদম

পূর্ববর্তী ডিরেক্টরিগুলির নাম / চালগুলি সহ সমস্ত প্রতিশ্রুতি সংরক্ষণের জন্য সমাধানটি খুঁজে পেয়েছে - এটি এই প্রশ্নের খুব উত্তরের রজারডপ্যাকের উত্তর।
অ্যাডাম

একমাত্র সমস্যা হ'ল আমি আর ক্লোন করা রেপো ব্যবহার করতে পারছি না
কিউলাং

5

( সম্ভবত?) git filter-branchএর একটি নতুন সংস্করণ ব্যবহার করে চলার সময় , এটি এই নতুন সরঞ্জামটি গিট-ফিল্টার-রেপো ব্যবহার করতে বলে । এই সরঞ্জামটি অবশ্যই আমার জন্য জিনিসগুলি সহজতর করেছে।git2.22+

ফিল্টার-রেপো দিয়ে ফিল্টারিং

XYZমূল প্রশ্ন থেকে রেপো তৈরি করার আদেশ :

# create local clone of original repo in directory XYZ
tmp $ git clone git@github.com:user/original.git XYZ

# switch to working in XYZ
tmp $ cd XYZ

# keep subdirectories XY1 and XY2 (dropping ABC)
XYZ $ git filter-repo --path XY1 --path XY2

# note: original remote origin was dropped
# (protecting against accidental pushes overwriting original repo data)

# XYZ $ ls -1
# XY1
# XY2

# XYZ $ git log --oneline
# last commit modifying ./XY1 or ./XY2
# first commit modifying ./XY1 or ./XY2

# point at new hosted, dedicated repo
XYZ $ git remote add origin git@github.com:user/XYZ.git

# push (and track) remote master
XYZ $ git push -u origin master

অনুমান: * রিমোট এক্সওয়াইজেড রেপো পুশের আগে নতুন এবং খালি ছিল

ফিল্টারিং এবং চলন্ত

আমার ক্ষেত্রে, আমি আরও সুসংগত কাঠামোর জন্য বেশ কয়েকটি ডিরেক্টরি সরিয়ে নিতে চেয়েছিলাম। প্রথমদিকে, আমি সেই সাধারণ filter-repoকমান্ডটি চালিয়েছিলাম git mv dir-to-renameতবে আমি পেয়েছি --path-renameবিকল্পটি ব্যবহার করে আমি কিছুটা "আরও ভাল" ইতিহাস পেতে পারি । 5 hours agoনতুন রেপোতে সরানো ফাইলগুলিতে সর্বশেষ পরিবর্তিত পরিবর্তে আমি এখন দেখছি last year(গিটহাব ইউআইতে), যা মূল রেপোতে পরিবর্তিত সময়ের সাথে মেলে।

পরিবর্তে...

git filter-repo --path XY1 --path XY2 --path inconsistent
git mv inconsistent XY3  # which updates last modification time

আমি শেষ পর্যন্ত দৌড়ে ...

git filter-repo --path XY1 --path XY2 --path inconsistent --path-rename inconsistent:XY3
মন্তব্য:
  • আমি ভেবেছিলাম গিট রেভ নিউজ ব্লগ পোস্টটি আরও একটি রেপো-ফিল্টারিং সরঞ্জাম তৈরি করার পিছনে যুক্তিটি ভালভাবে ব্যাখ্যা করেছে
  • আমি প্রথমদিকে মূল সংগ্রহস্থলে লক্ষ্য রেপো নামের সাথে মেলে একটি সাব-ডিরেক্টরি তৈরির পথটি চেষ্টা করেছি এবং তারপরে ফিল্টারিং (ব্যবহার করে git filter-repo --subdirectory-filter dir-matching-new-repo-name)। এই কমান্ড সেই সাব-ডাইরেক্টরিটিকে সঠিকভাবে অনুলিপি করা স্থানীয় স্থানীয় রেপোতে রূপান্তরিত করেছিল, কিন্তু এটির ফলে ডাইরেক্টরিটি তৈরি করতে কেবল তিনটি কমিটের ইতিহাসও তৈরি হয়েছিল। (আমি বুঝতে পারি নি যে এটি --pathএকাধিকবার নির্দিষ্ট করা যেতে পারে; এর মাধ্যমে সোর্স রেপোতে একটি উপ-ডিরেক্টরি তৈরি করার প্রয়োজনীয়তা অবলম্বন করে।) যেহেতু কেউ যখন সোর্স রেপোতে প্রতিশ্রুতিবদ্ধ হয়েছিল তখনই আমি লক্ষ্য করেছি যে আমি এগিয়ে যেতে ব্যর্থ হয়েছি ইতিহাস, আমি সবেমাত্র কমান্ডের git reset commit-before-subdir-move --hardপরে ব্যবহার করেছি cloneএবং কিছুটা সংশোধিত স্থানীয় ক্লোনটিতে এটি পরিচালনা --forceকরতে filter-repoকমান্ডটিতে যুক্ত করেছি।
git clone ...
git reset HEAD~7 --hard      # roll back before mistake
git filter-repo ... --force  # tell filter-repo the alterations are expected
  • আমি ইনস্টলটিতে স্ট্যাম্পড ছিলাম যেহেতু আমি এর সাথে এক্সটেনশন প্যাটার্ন সম্পর্কে অসচেতন ছিলাম git, তবে শেষ পর্যন্ত আমি গিট-ফিল্টার-রেপো ক্লোন করেছি এবং এটিতে সিমলিংক করেছি $(git --exec-path):
ln -s ~/github/newren/git-filter-repo/git-filter-repo $(git --exec-path)

1
নতুন সুপারিশ জন্য সম্মত filter-repoসরঞ্জাম (যা আমি গত মাসে উপস্থাপন stackoverflow.com/a/58251653/6309 )
VonC

git-filter-repoঅবশ্যই এই সময়ে অবশ্যই পছন্দসই পদ্ধতির হওয়া উচিত Using এটি তার থেকে অনেক বেশি দ্রুত এবং সুরক্ষিত git-filter-branchএবং গিট ইতিহাসের পুনর্লিখনের সময় যে প্রচুর গটচা চালাতে পারে তার বিরুদ্ধে সুরক্ষার ব্যবস্থা। আশা করি এই উত্তরটি আরও কিছুটা মনোযোগ পেয়েছে, কারণ এটিই সম্বোধনযোগ্য git-filter-repo
জেরেমি

4

আমার ঠিক এই সমস্যাটি ছিল তবে গিট ফিল্টার-শাখার উপর ভিত্তি করে সমস্ত স্ট্যান্ডার্ড সমাধান অত্যন্ত ধীর ছিল। আপনার যদি একটি ছোট সংগ্রহস্থল থাকে তবে এটি সমস্যা নাও হতে পারে, এটি আমার পক্ষে ছিল। আমি libgit2 এর উপর ভিত্তি করে আরও একটি গিট ফিল্টারিং প্রোগ্রাম লিখেছিলাম যা প্রথম ধাপ হিসাবে প্রাথমিক সংগ্রহস্থলের প্রতিটি ফিল্টারিংয়ের জন্য শাখা তৈরি করে এবং তারপরে এটিকে পরবর্তী ধাপ হিসাবে পরিষ্কার সংগ্রহস্থলে ঠেলে দেয়। আমার সংগ্রহশালায় (500Mb 100000 কমিট করে) স্ট্যান্ডার্ড গিট ফিল্টার-শাখা পদ্ধতিগুলিতে কয়েক দিন সময় লেগেছিল। আমার প্রোগ্রামটি একই ফিল্টারিং করতে কয়েক মিনিট সময় নেয়।

এটিতে গিট_ফিল্টারটির কল্পিত নাম রয়েছে এবং এটি এখানে বাস করে:

https://github.com/slobobaby/git_filter

গিটহাবে

আমি আশা করি এটি কারও কাজে লাগবে।


4

আপনার ট্যাগ এবং শাখাগুলি সংরক্ষণের সময় সাব-ডিরেক্টরিকে সরাতে এই ফিল্টার কমান্ডটি ব্যবহার করুন:

git filter-branch --index-filter \
"git rm -r -f --cached --ignore-unmatch DIR" --prune-empty \
--tag-name-filter cat -- --all

এখানে বিড়াল কি?
রজারডপ্যাক

4

এটির মূল্য কী তা জন্য, উইন্ডোজ মেশিনে গিটহাব কীভাবে ব্যবহার করা যায় তা এখানে। আসুন আমরা বলি যে আপনার কাছে একটি ক্লোন রেপো রয়েছে C:\dir1। ডিরেক্টরি গঠন ভালো দেখায়: C:\dir1\dir2\dir3dir3ডিরেক্টরি এক আমি একটি নতুন পৃথক রেপো হতে চান হয়।

GitHub:

  1. আপনার নতুন সংগ্রহস্থল তৈরি করুন: MyTeam/mynewrepo

বাশ প্রম্পট:

  1. $ cd c:/Dir1
  2. $ git filter-branch --prune-empty --subdirectory-filter dir2/dir3 HEAD
    ফিরে এসেছে: Ref 'refs/heads/master' was rewritten(fyi: dir2 / dir3 কেস সংবেদনশীল)

  3. $ git remote add some_name git@github.com:MyTeam/mynewrepo.git
    git remote add origin etc। কাজ হয়নি, ফিরে " remote origin already exists"

  4. $ git push --progress some_name master


3

আমি উপরে উল্লিখিত হিসাবে , আমি বিপরীত সমাধান (আমার স্পর্শ না সমস্ত কমান্ড মুছে ফেলা dir/subdir/targetdir) ব্যবহার করা হয়েছে যা প্রায় 95% কমিটগুলি (পছন্দসই) অপসারণ করে বেশ ভালভাবে কাজ করেছে বলে মনে হচ্ছে। দুটি ছোট সমস্যা বাকি আছে।

প্রথম , filter-branchকরে যা পরিচয় করিয়ে বা পরিবর্তন কোড কিন্তু দৃশ্যত, অপসারণ কাজ আপ ঠুং করেনি একত্রীকরণ করে Gitiverse তার স্টেশান তলদেশে হয়।

এটি একটি প্রসাধনী সমস্যা যার সাথে আমি সম্ভবত বেঁচে থাকতে পারি (তিনি বলেন ... চোখ এড়াতে আস্তে আস্তে পিছনে পিছনে ফিরে আসছে)

দ্বিতীয় যে কয়েকটি কমিট রয়ে গেছে তা সব থেকে অনেক বেশি নকল! আমি মনে করি যে একটি দ্বিতীয়, অপ্রয়োজনীয় সময়রেখা অর্জন করেছি যা প্রকল্পের পুরো ইতিহাস সম্পর্কে ছড়িয়ে পড়ে। মজার বিষয় (যা আপনি নীচের ছবি থেকে দেখতে পাচ্ছেন), তা হচ্ছে আমার তিনটি স্থানীয় শাখা একই টাইমলাইনে নেই (এটি অবশ্যই কেন বিদ্যমান এবং কেবল আবর্জনা সংগ্রহ করা হয়নি) isn't

কেবলমাত্র আমি কল্পনা করতে পারি যে মুছে ফেলা কমিটগুলির মধ্যে একটি হ'ল সম্ভবত, একক সংযুক্তিবদ্ধ প্রতিশ্রুতি যা filter-branch প্রকৃতপক্ষে মুছে ফেলেছিল এবং এটি এখন সমাহারিত স্ট্র্যান্ডের নিজস্ব প্রতিলিপিগুলির সাথে সমান্তরাল টাইমলাইন তৈরি করেছিল। ( অসহায়তা কোথায় আমার TARDiS এর?) আমি সুন্দর নিশ্চিত আমি এই বিষয়টি ঠিক করতে পারবো যদিও আমি চাই সত্যিই বুঝতে এটা ঘটেছে কিভাবে ভালোবাসি।

পাগল একীভূত-ও-রমার ক্ষেত্রে, আমি সম্ভবত সেই একাটিকে ছেড়ে চলে যাব কারণ এটি আমার দৃ commit়তার ইতিহাসে দৃ firm়তার সাথে নিজেকে জড়িয়ে রেখেছে - যখনই আমি কাছে আসি আমার দিকে ঝুঁকির ঘটনা - মনে হয় না এটি আসলে ঘটায় কোনও অ-প্রসাধনী সমস্যা এবং কারণ এটি টাওয়ার.অ্যাপে বেশ সুন্দর।


3

সহজ উপায়

  1. ইনস্টল git splitsজেকেটিংয়ের সমাধানের উপর ভিত্তি করে আমি এটিকে গিট এক্সটেনশন হিসাবে তৈরি করেছি ।
  2. ডিরেক্টরিগুলি স্থানীয় শাখায় বিভক্ত করুন #change into your repo's directory cd /path/to/repo #checkout the branch git checkout XYZ
    #split multiple directories into new branch XYZ git splits -b XYZ XY1 XY2

  3. কোথাও একটি খালি রেপো তৈরি করুন। আমরা ধরে নেব যে আমরা xyzগিটহাবের নামে একটি ফাঁকা রেপো তৈরি করেছি যার পথ রয়েছে:git@github.com:simpliwp/xyz.git

  4. নতুন রেপোতে চাপ দিন। #add a new remote origin for the empty repo so we can push to the empty repo on GitHub git remote add origin_xyz git@github.com:simpliwp/xyz.git #push the branch to the empty repo's master branch git push origin_xyz XYZ:master

  5. নতুন নির্মিত ডিরেক্টরিতে সদ্য নির্মিত রিমোট রেপো ক্লোন করুন
    #change current directory out of the old repo cd /path/to/where/you/want/the/new/local/repo #clone the remote repo you just pushed to git clone git@github.com:simpliwp/xyz.git


"সহজ উপায়" এর তুলনায় এই পদ্ধতির একটি সুবিধা হ'ল নতুন রেপোর জন্য ইতিমধ্যে রিমোট সেট আপ করা হয়েছে, তাই আপনি তত্ক্ষণাত সাবট্রি অ্যাড করতে পারেন। বাস্তবে এই git splits
এমএম

এই সমাধান পোস্ট করার জন্য অ্যান্ড্রুডের কাছে প্রপস। ওএসএক্স ( github.com/ricardoespsanto/git-splits ) এ কাজ করার জন্য আমি তার রেপো কাঁটাচামচ করেছি যদি তা অন্য কারওর জন্য উপযোগী হয়
রিকার্ডোসপসেন্টো

2

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

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


2

Https://github.com/vangorra/git_split এ গিট_স্প্লিট প্রকল্পটি দেখুন

গিট ডিরেক্টরিগুলি তাদের নিজস্ব অবস্থানে তাদের নিজস্ব নিজস্ব ভান্ডারে পরিণত করুন। কোনও সাবট্রি মজার ব্যবসা নেই। এই স্ক্রিপ্টটি আপনার গিট সংগ্রহস্থলের একটি বিদ্যমান ডিরেক্টরি গ্রহণ করবে এবং সেই ডিরেক্টরিটিকে তার নিজস্ব একটি স্বতন্ত্র ভাণ্ডারে পরিণত করবে। পথে, এটি আপনার সরবরাহিত ডিরেক্টরিটির পুরো পরিবর্তন ইতিহাসের অনুলিপি করবে।

./git_split.sh <src_repo> <src_branch> <relative_dir_path> <dest_repo>
        src_repo  - The source repo to pull from.
        src_branch - The branch of the source repo to pull from. (usually master)
        relative_dir_path   - Relative path of the directory in the source repo to split.
        dest_repo - The repo to push to.

1

এটি আপনার গিটকনফাইগে রাখুন:

reduce-to-subfolder = !sh -c 'git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter cookbooks/unicorn HEAD && git reset --hard && git for-each-ref refs/original/ | cut -f 2 | xargs -n 1 git update-ref -d && git reflog expire --expire=now --all && git gc --aggressive --prune=now && git remote rm origin'

1

আমি নিশ্চিত গিট সাবট্রিটি সমস্ত সূক্ষ্ম এবং দুর্দান্ত, তবে আমার গিট পরিচালিত কোডের উপ-ডিরেক্টরিগুলি যেটি আমি স্থানান্তর করতে চেয়েছিলাম তা সবই ছিল গ্রহনে। সুতরাং আপনি যদি উদাহরণ ব্যবহার করে থাকেন তবে এটি বেদনাদায়ক সহজ easy আপনি যে প্রকল্পটি স্থানান্তর করতে চান তা নিয়ে যান এবং টিম-> এটি সংযোগ বিচ্ছিন্ন করুন এবং তারপরে টিম-> এটিকে নতুন অবস্থানে ভাগ করুন। এটি পুরানো রেপো অবস্থানটি ব্যবহারের চেষ্টা করার জন্য ডিফল্ট হবে তবে আপনি ব্যবহার-বিদ্যমান নির্বাচনটি চেক করতে পারেন এবং এটি স্থানান্তরিত করতে নতুন জায়গাটি চয়ন করতে পারেন। সব শিলাবৃষ্টি।


3
সাবট্রিটির "সূক্ষ্ম এবং দুর্দান্ত" অংশটি হ'ল আপনার সাবডিরেক্টরির ইতিহাস যাত্রার জন্য আসে। আপনার যদি ইতিহাসের প্রয়োজন না হয় তবে আপনার বেদনাদায়ক সহজ পদ্ধতি হ'ল উপায়।
প্লেগজেন

0

আপনি সহজেই https://help.github.com/enterprise/2.15/user/articles/splitting-a-subfolder-out-into-a-new-repository/ চেষ্টা করতে পারেন

এটি আমার পক্ষে কাজ করেছে। উপরোক্ত পদক্ষেপগুলিতে আমি যে সমস্যার মুখোমুখি হয়েছিল সেগুলি হ'ল

  1. এ নির্দেশের git filter-branch --prune-empty --subdirectory-filter FOLDER-NAME BRANCH-NAME দ্য BRANCH-NAMEহয় মাস্টার

  2. সুরক্ষা সমস্যার কারণে প্রতিশ্রুতিবদ্ধ হওয়ার সময় যদি শেষ পদক্ষেপটি ব্যর্থ হয় তবে অনুসরণ করুন - https://docs.gitlab.com/ee/user/project/protected_branches.html


0

আমি বেশ সোজা ফরোয়ার্ড সমাধান খুঁজে পেয়েছি, ধারণাটি সংগ্রহস্থল অনুলিপি করা এবং তারপরে অপ্রয়োজনীয় অংশটি সরিয়ে ফেলতে হবে। এটা এভাবে কাজ করে:

1) আপনি যে ভাণ্ডারটি ভাগ করতে চান তা সঞ্চয় করুন one

git clone git@git.thehost.io:testrepo/test.git

2) গিট ফোল্ডারে সরান

cd test/

2) অপ্রয়োজনীয় ফোল্ডারগুলি সরান এবং এটি প্রতিশ্রুতিবদ্ধ

rm -r ABC/
git add .
enter code here
git commit -m 'Remove ABC'

3) বিএফজির সাহায্যে অপ্রয়োজনীয় ফোল্ডার (গুলি) ফর্মের ইতিহাস সরিয়ে দিন

cd ..
java -jar bfg.jar --delete-folders "{ABC}" test
cd test/
git reflog expire --expire=now --all && git gc --prune=now --aggressive

বহুগুণ ফোল্ডারগুলির জন্য আপনি কমা ব্যবহার করতে পারেন

java -jar bfg.jar --delete-folders "{ABC1,ABC2}" metric.git

4) পরীক্ষা করুন যে ইতিহাসে সবেমাত্র মুছে ফেলা ফাইল / ফোল্ডারগুলি নেই

git log --diff-filter=D --summary | grep delete

৫) এখন আপনার কাছে এবিসি ছাড়াই পরিষ্কার সংগ্রহস্থল রয়েছে, তাই এটি কেবল নতুন উত্সে ঠেলাও

remote add origin git@github.com:username/new_repo
git push -u origin master

এটাই. আপনি অন্য সংগ্রহস্থল পেতে পদক্ষেপগুলি পুনরাবৃত্তি করতে পারেন,

কেবল এক্সওয়াই 1, এক্সওয়াই 2 সরান এবং পদক্ষেপ 3 এ XYZ -> এবিসি নামকরণ করুন


প্রায় নিখুঁত ... তবে আপনি এখন খালি সমস্ত পুরানো কমিটগুলি অপসারণ করতে "গিট ফিল্টার-শাখা - ছাঁটাই ফাঁকা" ভুলে গেছেন। অরিজিনাল মাস্টারে ধাক্কা দেওয়ার আগে করণীয়!
জেটটাক্রিল

আপনি যদি ভুলটি করে থাকেন এবং এখনও পুরানো শূন্য প্রতিশ্রুতি অপসারণের পরে "পুনরায় চাপ দিতে" চান তবে সম্পাদনা করুন: "গিট পুশ-
ইউ অরিজিন্ট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.