কীভাবে 'গিট মার্জ' বিশদে কাজ করে?


95

আমি 'গিট মার্জ' এর পিছনে একটি সঠিক অ্যালগরিদম (বা তার কাছে) জানতে চাই want কমপক্ষে এই সাব-প্রশ্নের উত্তরগুলি সহায়ক হবে:

  • গিট কীভাবে একটি বিশেষ বিরোধবিরোধী পরিবর্তনের প্রসঙ্গে সনাক্ত করতে পারে?
  • গিট কীভাবে জানতে পারে যে এই সঠিক লাইনে একটি দ্বন্দ্ব রয়েছে?
  • কোনটি গিটকে স্বয়ংক্রিয়ভাবে সংহত করে?
  • শাখা মার্জ করার কোনও সাধারণ বেস না থাকলে গিট কীভাবে সম্পাদন করে?
  • শাখা মার্জ করার জন্য একাধিক সাধারণ ঘাঁটি থাকলে গিট কীভাবে সম্পাদন করে?
  • আমি একবারে একাধিক শাখা মার্জ করলে কী হবে?
  • মার্জ কৌশলগুলির মধ্যে পার্থক্য কী?

তবে পুরো অ্যালগরিদমের বর্ণনা আরও ভাল হবে।


8
আমার ধারণা আপনি এই উত্তরগুলি দিয়ে একটি পুরো বই পূরণ করতে পারবেন ...
ড্যানিয়েল হিলগার্থ

4
অথবা আপনি কেবল কোডটি পড়তে পেরেছিলেন, যা "পুরো অ্যালগরিদমের বর্ণনা দেওয়ার জন্য"
যতক্ষণ লাগবে

4
@ ড্যানিয়েলহিলগার্থ আমি এটি জানতে পেরে খুশি হব, যদি ইতিমধ্যে কোথাও কোথাও এরকম বই আছে। তথ্যসূত্র স্বাগত।
অতল 7

4
@ নতুনিক্রেনেল হ্যাঁ, আমি পারি। তবে এটি আরও সহজ হয়ে উঠতে পারে, যদি কেউ ইতিমধ্যে এই কোডের পিছনের তত্ত্বটি জানেন।
অতীতে 7

1. "একটি বিশেষ বিরোধবিরোধী পরিবর্তনের প্রসঙ্গ" কী? পয়েন্ট ২ এবং ৩. একই তবে উপেক্ষিত, আসুন এই দুটি প্রশ্ন একত্রিত করুন?
সিরো সান্তিলি 郝海东 冠状 病 六四 事件 法轮功

উত্তর:


65

3-ওয়ে মার্জ অ্যালগরিদমের বিবরণ খোঁজা আপনার পক্ষে সেরা হতে পারে। একটি উচ্চ-স্তরের বিবরণ এর কিছু হবে:

  1. একটি উপযুক্ত মার্জ বেসটি সন্ধান করুন B- ফাইলের একটি সংস্করণ যা নতুন সংস্করণ ( Xএবং Y) উভয়ের পূর্বপুরুষ এবং সাধারণত অতি সাম্প্রতিক ভিত্তি (যদিও এমন কিছু ক্ষেত্রে রয়েছে যেখানে এটি আরও পিছনে যেতে হবে, যা একটির মধ্যে একটি gitডিফল্ট বৈশিষ্ট্যrecursive একত্রীকরণের )
  2. এর Xসাথে Bএবং Yসাথে বিভিন্ন পারফর্ম করুন B
  3. দুটি ভিন্নতার মধ্যে চিহ্নিত পরিবর্তনের ব্লকগুলি দিয়ে চলুন। যদি উভয় পক্ষই একই স্থানে একই পরিবর্তন প্রবর্তন করে তবে যে কোনও একটি গ্রহণ করুন; যদি একটি পরিবর্তনের সাথে পরিচিত হয় এবং অন্যটি সেই অঞ্চলটিকে একা ছেড়ে দেয় তবে ফাইনালের পরিবর্তনের পরিচয় দিন; যদি উভয়ই কোনও স্থানে পরিবর্তনের পরিচয় দেয় তবে তা মিলছে না, ম্যানুয়ালি কোনও সংঘাতের সমাধান হওয়ার জন্য চিহ্নিত করুন।

সম্পূর্ণ অ্যালগরিদম এটিকে আরও বিশদে ডিল করে এবং এর সাথে কিছু ডকুমেন্টেশনও রয়েছে ( https://github.com/git/git/blob/master/Docamentation/technical/trivial- নিম . git help XXXtxt পৃষ্ঠাগুলি সহ যেখানে XXX এর অন্যতম merge-base, merge-file, merge, merge-one-fileএবং সম্ভবত অন্য কয়েকজন)। যদি এটি যথেষ্ট গভীর না হয় তবে সর্বদা সোর্স কোড থাকে ...


11

শাখা মার্জ করার জন্য একাধিক সাধারণ ঘাঁটি থাকলে গিট কীভাবে সম্পাদন করে?

এই নিবন্ধটি খুব সহায়ক ছিল: http://codicesoftware.blogspot.com/2011/09/ নিমজ্জন- রিসার্সিভ-strategy.html (এখানে অংশ 2 )।

পূর্বসূরী হিসাবে ব্যবহৃত হবে এমন ভার্চুয়াল শাখা উত্পন্ন করতে পুনরাবৃত্তির পুনরাবৃত্তভাবে ডিফার 3 ব্যবহার করে।

যেমন:

(A)----(B)----(C)-----(F)
        |      |       |
        |      |   +---+
        |      |   |
        |      +-------+
        |          |   |
        |      +---+   |
        |      |       |
        +-----(D)-----(E)

তারপরে:

git checkout E
git merge F

এখানে দুটি সেরা সাধারণ পূর্বপুরুষ (সাধারণ পূর্বপুরুষ যা অন্য কোনও পূর্বপুরুষ নয়) Cএবং D। গিট এগুলি একটি নতুন ভার্চুয়াল শাখায় মার্জ করে Vএবং তারপরে Vবেস হিসাবে ব্যবহার করে।

(A)----(B)----(C)--------(F)
        |      |          |
        |      |      +---+
        |      |      |
        |      +----------+
        |      |      |   |
        |      +--(V) |   |
        |          |  |   |
        |      +---+  |   |
        |      |      |   |
        |      +------+   |
        |      |          |
        +-----(D)--------(E)

আমি মনে করি গিট যদি আরও সেরা সাধারণ পূর্বপুরুষদের Vসাথে থাকে তবে পরের সাথে মিশে যায় with

নিবন্ধটিতে বলা হয়েছে যে ভার্চুয়াল শাখা তৈরি করার সময় যদি কোনও সংহত সংঘাত হয় তবে গিট বিবাদ চিহ্নিতকারীদের যেখানে সেখানে রয়েছে এবং এখনও অবিরত রেখে দেয়।

আমি একবারে একাধিক শাখা মার্জ করলে কী হবে?

@ নেভিক রেহেন যেভাবে ব্যাখ্যা করেছেন, এটি কৌশলের উপর নির্ভর করে, এটি ভালভাবে ব্যাখ্যা করা হয়েছে man git-merge MERGE STRATEGIES বিভাগে হয়েছে।

কেবলমাত্র octopusএবং ours/ theirsসমর্থন একসাথে একাধিক শাখা মার্জ করে,recursive উদাহরণস্বরূপ।

octopusসংঘাত হতে পারে যদি মার্জ করতে অস্বীকার, এবং oursএকটি তুচ্ছ সংশ্লেষ তাই কোনও বিবাদ হতে পারে না।

এই কমান্ডগুলির একটি নতুন প্রতিশ্রুতি উত্পন্ন হয় 2 টিরও বেশি পিতা-মাতা থাকবে।

আমি merge -X octopusগিট ১.৮.৫-এ একটি বিবাদ ছাড়াই এটি করেছি কীভাবে তা দেখে যায়।

প্রারম্ভিক অবস্থা:

   +--B
   |
A--+--C
   |
   +--D

কর্ম:

git checkout B
git merge -Xoctopus C D

নতুন রাষ্ট্র:

   +--B--+
   |     |
A--+--C--+--E
   |     |
   +--D--+

যেমনটি প্রত্যাশা করা হয়েছে, Eতার 3 জন বাবা-মা রয়েছে।

টোডো: কীভাবে অক্টোপাস একটি একক ফাইল সংশোধন করে ope পুনরাবৃত্তির দ্বি বাই-দ্বি 3-ওয়ে সংযুক্তি?

শাখা মার্জ করার কোনও সাধারণ বেস না থাকলে গিট কীভাবে সম্পাদন করে?

@ টোরেক উল্লেখ করেছেন যে ২.৯ থেকে, একত্রীকরণ ব্যতীত ব্যর্থ হয় --allow-unrelated-histories

আমি গিটার ১.৮.৫ এ পরীক্ষামূলকভাবে চেষ্টা করেছি:

git init
printf 'a\nc\n' > a
git add .
git commit -m a

git checkout --orphan b
printf 'a\nb\nc\n' > a
git add .
git commit -m b
git merge master

a রয়েছে:

a
<<<<<<< ours
b
=======
>>>>>>> theirs
c

তারপরে:

git checkout --conflict=diff3 -- .

a রয়েছে:

<<<<<<< ours
a
b
c
||||||| base
=======
a
c
>>>>>>> theirs

ব্যাখ্যা:

  • বেস খালি
  • বেসটি খালি থাকলে, কোনও একক ফাইলে কোনও পরিবর্তন সমাধান করা সম্ভব হয় না; কেবলমাত্র নতুন ফাইল সংযোজনের মতো বিষয়গুলি সমাধান করা যেতে পারে। উপরোক্ত দ্বন্দ্বটি বেসের সাথে 3-মুখী সংযোজনে সমাধান করা হবেa\nc\n একটি একক লাইন সংযোজন হিসাবে সংযোজনে সমাধান করা হবে
  • আমি মনে করি যে বেস ফাইল ছাড়াই 3-উপায় সংহতিকে 2-উপায় সংহত বলা হয়, যা কেবল একটি পৃথক

4
এই প্রশ্নের একটি নতুন এসও লিঙ্ক আছে, তাই আমি এই উত্তরের মাধ্যমে স্ক্যান করেছি (যা বেশ ভাল) এবং লক্ষ্য করেছি যে সাম্প্রতিক গিট পরিবর্তনটি গত বিভাগটিকে কিছুটা পুরানো করেছে। গিট সংস্করণ ২.৯ (প্রতিশ্রুতিবদ্ধ e379fdf34fee96cd205be83ff4e71699bdc32b18) থেকে, গিট এখন আপনি সংযোজন না করে যদি কোনও মার্জ বেস না থাকে তবে মার্জ করতে অস্বীকার করেছেন --allow-unrelated-histories
torek

4
এখানে @ ক্রো পোস্ট করা একের ফলো-আপ নিবন্ধটি দেওয়া হয়েছে: blog.plasticscm.com/2012/01/…
adam0101

আমি সর্বশেষে চেষ্টা করার পর থেকে আচরণটি পরিবর্তিত --allow-unrelated-historiesনা হলে: আপনি যে শাখাগুলি সংযুক্ত করছেন সেই শাখাগুলির মধ্যে কোনও সাধারণ ফাইল পাথ না থাকলে বাদ দেওয়া যেতে পারে।
জেরেমি তালিকা

ছোট সংশোধন: oursমার্জ কৌশল আছে, তবে কোনও theirsমার্জ কৌশল নেই। recursive+ theirsকৌশল কেবল দুটি শাখা সমাধান করতে পারে। git-scm.com/docs/git-
विस

9

আমিও আগ্রহী। আমি উত্তর জানি না, কিন্তু ...

একটি জটিল সিস্টেম যা কাজ করে তা অনায়াসে কাজ করে এমন একটি সাধারণ সিস্টেম থেকে বিকশিত হয়

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

আসুন কিছু পূর্ববর্তী অনুসন্ধান করার চেষ্টা করুন। থেকে git help merge-file:

git merge-file is designed to be a minimal clone of RCS merge; that is,
       it implements all of RCS merge's functionality which is needed by
       git(1).

উইকিপিডিয়া থেকে: http://en.wikedia.org/wiki/Git_%28software%29 -> http://en.wikedia.org/wiki/Three-way_ विस ## ত্রি- ওয়ে_ব্রিজ -> http: //en.wikedia .org / wiki / Diff3 -> http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf

সেই শেষ লিঙ্কটি একটি কাগজের পিডিএফ যা diff3বিস্তারিতভাবে অ্যালগরিদমকে বর্ণনা করে । এখানে একটি গুগল পিডিএফ-ভিউয়ার সংস্করণ । এটি কেবল 12 পৃষ্ঠার দীর্ঘ এবং অ্যালগরিদমটি কেবল কয়েকটি পৃষ্ঠাগুলি - তবে গাণিতিক একটি সম্পূর্ণ চিকিত্সা। এটি কিছুটা আনুষ্ঠানিক বলে মনে হতে পারে তবে আপনি যদি গিটের मर्জটি বুঝতে চান তবে আপনাকে প্রথমে সহজ সংস্করণটি বুঝতে হবে। আমি এখনও চেক করি নি, তবে এর মতো একটি নাম দিয়ে diff3আপনাকে সম্ভবত ডিফ বুঝতে হবে (যা একটি দীর্ঘকালীন সাধারণ উপগোষ্ঠী অ্যালগরিদম ব্যবহার করে)। তবে, diff3যদি আপনার কোনও গুগল থাকে তবে সেখানে আরও একটি স্বজ্ঞাত ব্যাখ্যা হতে পারে ...


এখন, আমি শুধু একটি পরীক্ষা তুলনা করেনি diff3এবং git merge-file। তারা একই তিন ইনপুট ফাইল নিতে version1 oldversion version2 এবং মার্ক দ্বন্দ্ব পথ একই সঙ্গে <<<<<<< version1, =======, >>>>>>> version2( diff3এছাড়াও আছে ||||||| oldversion), তাদের সাধারণ ঐতিহ্য দেখাচ্ছে।

আমি একটি খালি ফাইল ব্যবহার oldversion , এবং কাছাকাছি অভিন্ন ফাইল version1 এবং version2 মাত্র এক অতিরিক্ত লাইন দিয়ে যোগ করা version2

ফলাফল: git merge-fileএকক পরিবর্তিত রেখাকে দ্বন্দ্ব হিসাবে চিহ্নিত করেছে; তবে diff3পুরো দুটি ফাইলকে দ্বন্দ্ব হিসাবে বিবেচনা করেছেন। এইভাবে, ডিফ 3 হিসাবে পরিশীলিত হ'ল, গিটের সংযোজন এমনকি আরও পরিশীলিত, এমনকি এই সাধারণতম ক্ষেত্রেও।

এখানে আসল ফলাফল রয়েছে (আমি পাঠ্যের জন্য @ টওয়ালবার্গের উত্তর ব্যবহার করেছি)। প্রয়োজনীয় বিকল্পগুলি নোট করুন (স্বতন্ত্র ম্যানেজগুলি দেখুন)।

$ git merge-file -p fun1.txt fun0.txt fun2.txt

You might be best off looking for a description of a 3-way merge algorithm. A
high-level description would go something like this:

    Find a suitable merge base B - a version of the file that is an ancestor of
both of the new versions (X and Y), and usually the most recent such base
(although there are cases where it will have to go back further, which is one
of the features of gits default recursive merge) Perform diffs of X with B and
Y with B.  Walk through the change blocks identified in the two diffs. If both
sides introduce the same change in the same spot, accept either one; if one
introduces a change and the other leaves that region alone, introduce the
change in the final; if both introduce changes in a spot, but they don't match,
mark a conflict to be resolved manually.
<<<<<<< fun1.txt
=======
THIS IS A BIT DIFFERENT
>>>>>>> fun2.txt

The full algorithm deals with this in a lot more detail, and even has some
documentation (/usr/share/doc/git-doc/technical/trivial-merge.txt for one,
along with the git help XXX pages, where XXX is one of merge-base, merge-file,
merge, merge-one-file and possibly a few others). If that's not deep enough,
there's always source code...

$ diff3 -m fun1.txt fun0.txt fun2.txt

<<<<<<< fun1.txt
You might be best off looking for a description of a 3-way merge algorithm. A
high-level description would go something like this:

    Find a suitable merge base B - a version of the file that is an ancestor of
both of the new versions (X and Y), and usually the most recent such base
(although there are cases where it will have to go back further, which is one
of the features of gits default recursive merge) Perform diffs of X with B and
Y with B.  Walk through the change blocks identified in the two diffs. If both
sides introduce the same change in the same spot, accept either one; if one
introduces a change and the other leaves that region alone, introduce the
change in the final; if both introduce changes in a spot, but they don't match,
mark a conflict to be resolved manually.

The full algorithm deals with this in a lot more detail, and even has some
documentation (/usr/share/doc/git-doc/technical/trivial-merge.txt for one,
along with the git help XXX pages, where XXX is one of merge-base, merge-file,
merge, merge-one-file and possibly a few others). If that's not deep enough,
there's always source code...
||||||| fun0.txt
=======
You might be best off looking for a description of a 3-way merge algorithm. A
high-level description would go something like this:

    Find a suitable merge base B - a version of the file that is an ancestor of
both of the new versions (X and Y), and usually the most recent such base
(although there are cases where it will have to go back further, which is one
of the features of gits default recursive merge) Perform diffs of X with B and
Y with B.  Walk through the change blocks identified in the two diffs. If both
sides introduce the same change in the same spot, accept either one; if one
introduces a change and the other leaves that region alone, introduce the
change in the final; if both introduce changes in a spot, but they don't match,
mark a conflict to be resolved manually.
THIS IS A BIT DIFFERENT

The full algorithm deals with this in a lot more detail, and even has some
documentation (/usr/share/doc/git-doc/technical/trivial-merge.txt for one,
along with the git help XXX pages, where XXX is one of merge-base, merge-file,
merge, merge-one-file and possibly a few others). If that's not deep enough,
there's always source code...
>>>>>>> fun2.txt

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


2

আসল বাস্তবায়ন এখানে

http://git.kaarsemaker.net/git/blob/857f26d2f41e16170e48076758d974820af685ff/git- विसর- রেকর্ডিভ.পি

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


লিঙ্কটি নিচে রয়েছে।
চুজুন গান

0

গিট কীভাবে একটি বিশেষ বিরোধবিরোধী পরিবর্তনের প্রসঙ্গে সনাক্ত করতে পারে?
গিট কীভাবে জানতে পারে যে এই সঠিক লাইনে একটি দ্বন্দ্ব রয়েছে?

যদি একই লাইনটি মার্জারের উভয় দিকে পরিবর্তিত হয়, তবে এটি একটি বিরোধ; যদি তাদের না থাকে, তবে এক দিক থেকে পরিবর্তন (যদি বিদ্যমান থাকে) গৃহীত হয়।

কোনটি গিটকে স্বয়ংক্রিয়ভাবে সংহত করে?

যে পরিবর্তনগুলি বিরোধী নয় (উপরে দেখুন)

শাখা মার্জ করার জন্য একাধিক সাধারণ ঘাঁটি থাকলে গিট কীভাবে সম্পাদন করে?

গিট মার্জ-বেসের সংজ্ঞা অনুসারে , কেবলমাত্র একটি (সর্বশেষ সাধারণ পূর্বপুরুষ) রয়েছে।

আমি একবারে একাধিক শাখা মার্জ করলে কী হবে?

এটি মার্জ কৌশলের উপর নির্ভর করে (কেবলমাত্র octopusএবং ours/ theirsকৌশলগুলি দুটিরও বেশি শাখা মার্জ করার পক্ষে সমর্থন করে)।

মার্জ কৌশলগুলির মধ্যে পার্থক্য কী?

git mergeম্যানপেজে এটি ব্যাখ্যা করা হয়েছে ।


4
'একই লাইন' এর অর্থ কী? আমি যদি অন্য দু'জনের মধ্যে নতুন অ-খালি লাইন andোকানো এবং মার্জ করি - কোন লাইন একই? যদি আমি একটি শাখায় কিছু লাইন মুছে ফেলি, তবে অন্য শাখায় কোনটি 'একই'?
অতীতে 7

4
পাঠ্যে উত্তর দেওয়াটা কিছুটা জটিল। গিট দুটি ফাইলের (বা কোনও ফাইলের দুটি সংশোধন) এর মধ্যে পার্থক্য প্রকাশ করতে [ডিফএস] (এন.ইউইকিপিডিয়া.org / উইকি / ডিফ) ব্যবহার করে। প্রসঙ্গের তুলনায় লাইনগুলি যুক্ত করা বা অপসারণ করা হয়েছে কিনা তা সনাক্ত করতে পারে (ডিফল্টরূপে, তিনটি লাইন)। "একই লাইন" এর অর্থ সংযোজন এবং মোছার বিষয়টি মাথায় রেখে প্রসঙ্গে।
নেভিক রেহেনেল

4
আপনি পরামর্শ দিচ্ছেন যে "একই লাইন" পরিবর্তন কোনও সংঘাতের ইঙ্গিত দেয়। অটোমেজ ইঞ্জিনটি কি আসলেই লাইন ভিত্তিক? নাকি এটি কুনি-ভিত্তিক? সেখানে কি কেবল এক সাধারণ পূর্বপুরুষ? যদি তাই হয় তবে কেন git-merge-recursiveবিদ্যমান?
এডওয়ার্ড থমসন

4
@ অ্যাডওয়ার্ড থমসন: হ্যাঁ, রেজোলিউশনটি লাইন-ভিত্তিক (কেবলমাত্র একটি লাইন বাকি না হওয়া পর্যন্ত কুকুরটিকে ছোট ছোট শিকারীদের মধ্যে ভেঙে ফেলা যায়)। ডিফল্ট মার্জ কৌশলটি সর্বশেষ সাধারণ পূর্বপুরুষকে রেফারেন্স হিসাবে ব্যবহার করে তবে আপনি অন্য কিছু ব্যবহার করতে চাইলে অন্যরাও আছেন। এবং আমি কী git-merge-recursiveহতে হবে তা জানি না (কোনও ম্যান পেজ নেই এবং গুগল কিছুই দেয় না)। এ সম্পর্কে আরও তথ্য git mergeএবং git merge-baseম্যান পৃষ্ঠাতে পাওয়া যাবে ।
নেভিক রেহেনেল

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