গিট মার্জ: কোডে পরিবর্তনগুলি প্রয়োগ করুন যা একটি ভিন্ন ফাইলে স্থানান্তরিত হয়েছে


132

আমি এই মুহুর্তে একটি চমত্কার গরুর গিফট মার্জ কসরত চেষ্টা করছি। একটি সমস্যা যা আমি আসছি তা হ'ল আমি আমার শাখার কিছু কোডে কিছু পরিবর্তন করেছি, তবে আমার সহকর্মী সেই কোডটি তার শাখায় একটি নতুন ফাইলে স্থানান্তরিত করেছেন। সুতরাং যখন আমি করেছি git merge my_branch his_branch, গিটটি খেয়াল করতে পারেনি যে নতুন ফাইলে কোডটি পুরনোটির মতো এবং তাই আমার পরিবর্তনগুলির কোনওটিই সেখানে নেই।

নতুন ফাইলগুলিতে কোডে আবার আমার পরিবর্তনগুলি প্রয়োগ করার সবচেয়ে সহজ উপায়। কোন কমিটগুলি পুনরায় প্রয়োগ করা দরকার তা সন্ধান করতে আমার খুব বেশি সমস্যা হবে না (আমি কেবল ব্যবহার করতে পারি git log --stat)। তবে আমি যতদূর বলতে পারি, নতুন ফাইলগুলিতে পরিবর্তনগুলি পুনরায় প্রয়োগ করার জন্য গিট পাওয়ার কোনও উপায় নেই। আমি এখন দেখতে পাচ্ছি সবচেয়ে সহজ জিনিস হ'ল পরিবর্তনগুলি ম্যানুয়ালি পুনরায় প্রয়োগ করা, যা কোনও ভাল ধারণার মতো দেখাচ্ছে না।

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


2
: কোনো ঠিক একই, কিন্তু এখানে ভাল anwsers সঙ্গে একটি অনুরূপ প্রশ্ন প্রযোজ্য পারে stackoverflow.com/questions/2701790/...
মারিয়ানো Desanze

4
উত্তরের কোনওটিই বর্ণনা করে না যে গিটটি কেন স্বয়ংক্রিয়ভাবে এই জাতীয় সংযোজন করতে সক্ষম হয় না। আমি ভেবেছিলাম যে নামগুলি সনাক্ত করতে এবং স্বয়ংক্রিয়ভাবে উপযুক্ত মার্জটি সম্পাদন করার জন্য এটি যথেষ্ট স্মার্ট হওয়ার কথা?
জন

প্রশ্নটি জিজ্ঞাসা করার সময় সম্ভবত এটি সত্য ছিল না, তবে গিটের আধুনিক সংস্করণগুলি (আমি 1.9.5 ব্যবহার করছি) নাম পরিবর্তন করা এবং সরানো ফাইলগুলিতে পরিবর্তনগুলিকে একত্রিত করতে পারে। এমনকি --rename-thresholdপ্রয়োজনীয়তার পরিমাণের সামঞ্জস্য করার জন্য একটি বিকল্পও রয়েছে।
টড ওভেন

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

আপনি যদি প্রথমে রিবেস করেন তবে / এটি কি কোনও সমস্যা ছিল?
hbogert

উত্তর:


132

আমার অনুরূপ সমস্যা ছিল এবং আমি লক্ষ্য ফাইল সংস্থার সাথে মেলে আমার কাজটি ছাড় দিয়ে সমাধান করেছি।

বলুন যে আপনি original.txtআপনার শাখায় ( localশাখা) পরিবর্তন করেছেন , তবে মাস্টার শাখায়, original.txtঅন্য একটিতে অনুলিপি করেছেন, বলুন copy.txt। এই অনুলিপি একটি প্রতিশ্রুতিবদ্ধ হয়ে গেছে যে আমরা অঙ্গীকারবদ্ধ নামকরণ CP

আপনি আপনার স্থানীয় পরিবর্তনগুলি, প্রতিশ্রুতিবদ্ধ Aএবং Bনীচে, যা চালু হয়েছিল original.txtনতুন ফাইলটিতে প্রয়োগ করতে চান copy.txt

 ---- X -----CP------ (master)
       \ 
        \--A---B--- (local)

moveএর সাথে আপনার পরিবর্তনের শুরুতে একটি নিক্ষেপ শাখা তৈরি করুন git branch move X। এর অর্থ হল, moveশাখাটি কমিট করে রাখুন X, যেটি আপনি সংহত করতে চান তার আগে যেটি অঙ্গীকার করে; সম্ভবত, এটি সেই প্রতিশ্রুতি থেকে আপনি নিজের পরিবর্তনগুলি বাস্তবায়নের জন্য ব্রাঞ্চ আউট করেছিলেন। ব্যবহারকারী @ ডিজিরি ডু নীচে লিখেছেন, আপনি git merge-base master localএটি সন্ধান করতে পারেন X

 ---- X (move)-----CP----- (master)
       \ 
        \--A---B--- (local)

এই শাখায়, নিম্নলিখিত নামকরণের আদেশটি জারি করুন:

git mv original.txt copy.txt

এটি ফাইলটির নতুন নামকরণ করে। নোট করুন যে copy.txtএই মুহুর্তে আপনার গাছে এখনও উপস্থিত ছিল না।
আপনার পরিবর্তন প্রতিশ্রুতিবদ্ধ (আমরা এই প্রতিশ্রুতি নামকরণ MV)।

        /--MV (move)
       /
 ---- X -----CP----- (master)
       \ 
        \--A---B--- (local)

আপনি এখন উপরে আপনার কাজটি পুনঃনির্মাণ করতে পারেন move:

git rebase move local

এটি সমস্যা ছাড়াই কাজ করা উচিত এবং আপনার পরিবর্তনগুলি copy.txtআপনার স্থানীয় শাখায় প্রয়োগ করা হয়।

        /--MV (move)---A'---B'--- (local)
       /
 ---- X -----CP----- (master)

এখন, আপনি অগত্যা MVআপনার প্রধান শাখার ইতিহাসে প্রতিশ্রুতিবদ্ধতা চান বা প্রয়োজন নেই , কারণ মুভ অপারেশনটি CPমূল শাখায় কমিট করার সময় অনুলিপি অপারেশনের সাথে দ্বন্দ্বের কারণ হতে পারে ।

আপনাকে কেবল নিজের কাজটি পুনরায় শোধ করতে হবে, সরানো ক্রিয়াকলাপটি নিম্নলিখিতভাবে বাদ দিয়ে:

git rebase move local --onto CP

... যেখানে অন্য শাখায় চালু হয়েছিল CPকমিট যেখানে copy.txt। এটি কমিটের copy.txtউপরে থাকা সমস্ত পরিবর্তনকে প্রত্যাখ্যান করে CP। এখন, আপনার localশাখাটি হুবহু হ'ল আপনি সর্বদা সংশোধন করেছেন copy.txtএবং না original.txtএবং আপনি অন্যের সাথে মিশে যেতে পারেন।

                /--A''---B''-- (local)
               /
 -----X-------CP----- (master)

এটি গুরুত্বপূর্ণ যে পরিবর্তনগুলি প্রয়োগ করা হয় CPবা অন্যথায় copy.txtবিদ্যমান ছিল না এবং পরিবর্তনগুলি আবার প্রয়োগ করা হবে original.txt

আশা করি এটি পরিষ্কার হয়ে গেছে। এই উত্তরটি দেরিতে আসে তবে এটি অন্য কারও পক্ষে কার্যকর হতে পারে।


2
এটি অনেক কাজ, তবে আমি মনে করি এটি নীতিগতভাবে কাজ করা উচিত। যদিও আমি মনে করি রিবেসের চেয়ে মার্জ করার সাথে আপনার ভাগ্য ভাল।
asmeurer

7
এই সমাধানটিতে প্যাচগুলি সম্পাদনা করা বা ব্যবহারের বিপরীতে কেবলমাত্র বেসরকারী গিট কমান্ড patchজড়িত রয়েছে (যার মধ্যে বেশিরভাগ কাজও জড়িত), এবং এই কারণেই আমি ভেবেছিলাম এটি এটিকে দেখানো আকর্ষণীয় হতে পারে। এছাড়াও, নোট করুন যে আমি আমার ক্ষেত্রে আসলে পরিবর্তনগুলি প্রয়োগ করার চেয়ে উত্তরটি লিখতে বেশি সময় নিয়েছি। কোন ধাপে আপনি মার্জটি ব্যবহার করে পুনঃনির্দেশ চান? এবং কেন? কেবলমাত্র তফাতটি আমি দেখতে পাচ্ছি তা হল প্রত্যাখ্যান করার মাধ্যমে, আমি একটি অস্থায়ী প্রতিশ্রুতি করি যা পরে বাতিল করা হয় (প্রতিশ্রুতিবদ্ধ MV), যা কেবল মার্জ করেই সম্ভব নয়।
coredump

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

4
আমি পদ্ধতির বিষয়টি স্পষ্ট করতে কয়েকটি ASCII গাছ যুক্ত করেছি। সেক্ষেত্রে মার্জ বনাম রিবাজে পুনঃনির্মাণ: আমি যা করতে চাই তা হ'ল আমার শাখায় 'অরিজিনাল টেক্সট' এ সমস্ত পরিবর্তন আনা হয় এবং মাস্টার শাখায় 'কপি.টেক্সট' এ প্রয়োগ করা হয় কারণ কোনও কারণে 'আসল'। txt 'কোনও সময়ে' copy.txt 'এ অনুলিপি করা হয়েছিল (এবং সরানো হয়নি)। সেই অনুলিপিটির পরে, 'original.txt' মাস্টার শাখায়ও বিকশিত হতে পারে। আমি যদি সরাসরি একত্রীভূত হয়ে যাই তবে মূল.txt এ আমার স্থানীয় পরিবর্তনগুলি মাস্টার শাখায় পরিবর্তিত অরিজিনাল টেক্সটটিতে প্রয়োগ করা হবে, যা মার্জ করা কঠিন। শুভেচ্ছা।
coredump

1
যাইহোক, যদিও আমি বিশ্বাস করি যে এই সমাধানটি কার্যকর হবে (যদিও আমি ধন্যবাদ জানাতে এখনই চেষ্টা করার মতো পরিস্থিতি নেই), তাই আপাতত আমি এটিকে উত্তর হিসাবে চিহ্নিত করব।
asmeurer

31

আপনি সর্বদা প্যাচ তৈরি করতে git diff(বা git format-patch) ব্যবহার করতে পারেন , তারপরে প্যাচটিতে ম্যানুয়ালি ফাইলের নামগুলি সম্পাদনা করুন এবং এটি git apply(বা git am) দিয়ে প্রয়োগ করুন ।

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


1
আচ্ছা, এটি এখন পর্যন্ত সেরা উত্তর। প্রতিশ্রুতিবদ্ধভাবে কীভাবে git format-patchকাজ করা যায় তা আমি বুঝতে পারি না। যদি আমি git format-patch SHA1এটি করি , এটি পুরো ইতিহাসের জন্য প্যাচ ফাইলগুলির পুরো গোছা তৈরি করে। তবে আমার ধারণা git show SHA1 > diff.patchঠিক তেমন কাজ করবে।
asmeurer

1
@ এসম্যুরার: -1বিকল্পটি ব্যবহার করুন । ফর্ম্যাট-প্যাচের জন্য অপারেশনের সাধারণ মোড একটি রিভিশন রেঞ্জ, এর মতো origin/master..master, যাতে আপনি সহজেই কোনও প্যাচ সিরিজ প্রস্তুত করতে পারেন।
ক্যাসাবেল

1
আসলে, অন্য নোট। git applyএবং git amখুব পিক, কারণ তারা একই লাইন নম্বর চায়। তবে আমি বর্তমানে ইউএনআইএক্স patchকমান্ড দিয়ে সফল হচ্ছি ।
asmeurer

24

পুনঃনামকরণ এবং সম্পাদনার সাথে একত্রীকরণের বিরোধের মুখোমুখি হওয়ার একত্রীকরণের সমাধানটি এখানে দেওয়া হয়েছে এবং সঠিক 3 মার্জ উত্স ফাইলগুলি সনাক্ত করে মার্জেটুলের সাথে সমাধান করা হয়েছে।

  • 'মুছে ফেলা ফাইল' এর কারণে মার্জ ব্যর্থ হওয়ার পরে আপনি বুঝতে পেরেছিলেন যে নাম পরিবর্তন করে সম্পাদনা করা হয়েছে:

    1. আপনি মার্জটি বাতিল করে দিন।
    2. আপনার শাখায় ফাইলের নাম পরিবর্তন করে প্রতিশ্রুতিবদ্ধ।
    3. এবং আবার মার্জ।

হাঁটুন-থ্রু:

একটি file.txt তৈরি করুন:

$ git init
Initialized empty Git repository in /tmp/git-rename-and-modify-test/.git/

$ echo "A file." > file.txt
$ git add file.txt
$ git commit -am "file.txt added."
[master (root-commit) 401b10d] file.txt added.
 1 file changed, 1 insertion(+)
 create mode 100644 file.txt

একটি শাখা তৈরি করুন যেখানে আপনি পরে সম্পাদনা করবেন:

$ git branch branch-with-edits
Branch branch-with-edits set up to track local branch master.

নতুন নামটি তৈরি করুন এবং মাস্টারে সম্পাদনা করুন:

$ git mv file.txt renamed-and-edited.txt
$ echo "edits on master" >> renamed-and-edited.txt 
$ git commit -am "file.txt + edits -> renamed-and-edited.txt."
[master def790f] file.txt + edits -> renamed-and-edited.txt.
 2 files changed, 2 insertions(+), 1 deletion(-)
 delete mode 100644 file.txt
 create mode 100644 renamed-and-edited.txt

শাখায় অদলবদল করুন, এবং সেখানে সম্পাদনা করুন:

$ git checkout branch-with-edits 
Switched to branch 'branch-with-edits'
Your branch is behind 'master' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)
$ 
$ echo "edits on branch" >> file.txt 
$ git commit -am "file.txt edited on branch."
[branch-with-edits 2c4760e] file.txt edited on branch.
 1 file changed, 1 insertion(+)

মাস্টারকে মার্জ করার চেষ্টা করুন:

$ git merge master
CONFLICT (modify/delete): file.txt deleted in master and modified in HEAD. Version HEAD of file.txt left in tree.
Automatic merge failed; fix conflicts and then commit the result.

লক্ষ্য করুন যে দ্বন্দ্বটি সমাধান করা শক্ত - এবং সেই ফাইলগুলির নাম পরিবর্তন করা হয়েছিল। বাতিল করুন, নামটির নকল করুন:

$ git merge --abort
$ git mv file.txt renamed-and-edited.txt
$ git commit -am "Preparing for merge; Human noticed renames files were edited."
[branch-with-edits ca506da] Preparing for merge; Human noticed renames files were edited.
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename file.txt => renamed-and-edited.txt (100%)

আবার মার্জ করার চেষ্টা করুন:

$ git merge master
Auto-merging renamed-and-edited.txt
CONFLICT (add/add): Merge conflict in renamed-and-edited.txt
Recorded preimage for 'renamed-and-edited.txt'
Automatic merge failed; fix conflicts and then commit the result.

গ্রেট! মার্জুলের সাথে সমাধান করা যেতে পারে এমন একটি 'স্বাভাবিক' দ্বন্দ্বের ফলাফলগুলি মার্জ করুন:

$ git mergetool
Merging:
renamed-and-edited.txt

Normal merge conflict for 'renamed-and-edited.txt':
  {local}: created file
  {remote}: created file
$ git commit 
Recorded resolution for 'renamed-and-edited.txt'.
[branch-with-edits 2264483] Merge branch 'master' into branch-with-edits

মজাদার. পরের বার যখন আমি এই সমস্যাটি প্রকাশ করব তখন আমাকে এটি চেষ্টা করতে হবে।
asmeurer

1
এই সমাধানটিতে, আমার কাছে মনে হয় যে প্রথম পদক্ষেপটি, যে মার্জটি বাতিল হয়ে গেছে, কেবল কোনও ফাইলের নাম পরিবর্তন করা হয়েছে এবং দূরবর্তীভাবে সম্পাদনা করা হয়েছিল তা খুঁজে বের করার জন্য এটি দরকারী। আপনি যদি তাদের আগে থেকেই জানেন। আপনি এই পদক্ষেপটি এড়িয়ে যেতে পারেন এবং মূলত, সমাধানটি হ'ল স্থানীয়ভাবে ফাইলগুলির নাম পরিবর্তন করা এবং তারপরে সংযুক্ত করা এবং বিবাদগুলি যথারীতি সমাধান করা।

1
ধন্যবাদ. আমার অবস্থা ঐ আমি সরানো ছিল B.txt -> C.txtএবং A.txt -> B.txtGit এমভি, এবং Git স্বয়ংক্রিয়ভাবে সঠিকভাবে একত্রীকরণ দ্বন্দ্ব মেলে না পারে সঙ্গে (পুরাতন মধ্যে পেয়ে একত্রীকরণ দ্বন্দ্ব ছিল B.txtএবং নতুন B.txt)। এই পদ্ধতিটি ব্যবহার করে, মার্জ সংঘাতগুলি এখন সঠিক ফাইলগুলির মধ্যে রয়েছে।
সিবি

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