سؤال

عند دمج فرع الموضوع "B" في "A" باستخدام git merge, ، أحصل على بعض الصراعات.أعلم أنه يمكن حل جميع التعارضات باستخدام الإصدار الموجود في "B".

أنا على علم بذلك git merge -s ours.ولكن ما أريده هو شيء من هذا القبيل git merge -s theirs.

لماذا غير موجود؟كيف يمكنني تحقيق نفس النتيجة بعد الدمج المتعارض مع الموجود git أوامر؟(git checkout كل ملف غير مدمج من B)

تحديث:"الحل" المتمثل في تجاهل أي شيء من الفرع A (نقطة التزام الدمج إلى الإصدار B من الشجرة) ليس هو ما أبحث عنه.

هل كانت مفيدة؟

المحلول

أضف ال -X خيار ل theirs. فمثلا:

git checkout branchA
git merge -X theirs branchB

كل شيء سوف يندمج في الطريقة المطلوبة.

الشيء الوحيد الذي رأيته هو السبب هو إذا تم حذف الملفات من BranchB. يظهرون كصراعات إذا فعل شيء آخر غير جيت الإزالة.

الإصلاح سهل. فقط الجري git rm مع اسم أي ملفات تم حذفها:

git rm {DELETED-FILE-NAME}

بعد ذلك ، -X theirs يجب أن تعمل كما هو متوقع.

بالطبع ، القيام بالإزالة الفعلية مع git rm سيمنع القيادة الصراع من الحدوث في المقام الأول.


ملحوظة: خيار شكل أطول موجود أيضا. لاستخدامه ، استبدل:

-X theirs

مع:

--strategy-option=theirs

نصائح أخرى

حل ممكن ومختبر لدمج BranchB في فرعنا المسحوق:

# in case branchA is not our current branch
git checkout branchA

# make merge commit but without conflicts!!
# the contents of 'ours' will be discarded later
git merge -s ours branchB    

# make temporary branch to merged commit
git branch branchTEMP         

# get contents of working tree and index to the one of branchB
git reset --hard branchB

# reset to our merged commit but 
# keep contents of working tree and index
git reset --soft branchTEMP

# change the contents of the merged commit
# with the contents of branchB
git commit --amend

# get rid off our temporary branch
git branch -D branchTEMP

# verify that the merge commit contains only contents of branchB
git diff HEAD branchB

لأتمتة ذلك ، يمكنك لفه في برنامج نصي باستخدام Brancha و BranchB كوسيطات.

يحافظ هذا الحل على الوالد الأول والثاني لالتزام الدمج ، تمامًا كما تتوقع git merge -s theirs branchB.

سمحت لك الإصدارات القديمة من GIT باستخدام استراتيجية دمج "لهم":

git pull --strategy=theirs remote_branch

ولكن تمت إزالة هذا منذ ذلك الحين ، كما هو موضح في هذه الرسالة بواسطة جونيو هامانو (المشرف GIT). كما هو مذكور في الرابط ، بدلاً من ذلك ستفعل ذلك:

git fetch origin
git reset --hard origin

احذر ، على الرغم من أن هذا يختلف عن دمج فعلي. ربما يكون الحل الخاص بك هو الخيار الذي تبحث عنه حقًا.

لقد استخدمت الجواب من بول بلديج منذ الآن. اكتشفت أنه يمكنك القيام بدمج "طبيعي" ، تحدث الصراعات ، لذلك تفعل

git checkout --theirs <file>

لحل الصراع باستخدام المراجعة من الفرع الآخر. إذا قمت بذلك لكل ملف ، فلديك نفس السلوك كما تتوقع منه

git merge <branch> -s theirs

على أي حال ، فإن الجهد أكثر مما سيكون مع دمج Strategy! (تم اختبار هذا مع GIT الإصدار 1.8.0)

ليس من الواضح تمامًا ماهية النتيجة المرجوة ، لذلك هناك بعض الالتباس حول الطريقة "الصحيحة" للقيام بذلك في الإجابات وتعليقاتهم. أحاول تقديم نظرة عامة وأرى الخيارات الثلاثة التالية:

حاول الدمج واستخدم B للصراعات

هذا هو ليس "نسخةهم git merge -s ours"لكن نسخةهم" git merge -X ours"(وهو قصير ل git merge -s recursive -X ours):

git checkout branchA
# also uses -s recursive implicitly
git merge -X theirs branchB

هذا ما مثل إجابة آلان دبليو سميث يفعل.

استخدم المحتوى من B فقط

هذا يخلق دمجًا لكلا الفرعين ولكنه يتجاهل كل التغييرات من branchA ويحتفظ فقط المحتويات من branchB.

# Get the content you want to keep.
# If you want to keep branchB at the current commit, you can add --detached,
# else it will be advanced to the merge commit in the next step.
git checkout branchB

# Do the merge an keep current (our) content from branchB we just checked out.
git merge -s ours branchA

# Set branchA to current commit and check it out.
git checkout -B branchA

لاحظ أن الاندماج يرتكب الوالد الأول الآن هو ذلك من branchB والثاني فقط من branchA. هذا ما مثل إجابة Gandalf458 يفعل.

استخدم المحتوى من B فقط واحتفظ بترتيب الوالدين الصحيح

هذا هو النسخة الحقيقية " git merge -s ours"يحتوي على نفس المحتوى كما في الخيار من قبل (أي فقط من ذلك branchB) لكن ترتيب الوالدين صحيح ، أي يأتي الوالد الأول branchA والثاني من branchB.

git checkout branchA

# Do a merge commit. The content of this commit does not matter,
# so use a strategy that never fails.
# Note: This advances branchA.
git merge -s ours branchB

# Change working tree and index to desired content.
# --detach ensures branchB will not move when doing the reset in the next step.
git checkout --detach branchB

# Move HEAD to branchA without changing contents of working tree and index.
git reset --soft branchA

# 'attach' HEAD to branchA.
# This ensures branchA will move when doing 'commit --amend'.
git checkout branchA

# Change content of merge commit to current index (i.e. content of branchB).
git commit --amend -C HEAD

هذا هو ما إجابة بول بلديجس لا (دون الحاجة إلى فرع مؤقت).

لقد حلت مشكلتي باستخدام

git checkout -m old
git checkout -b new B
git merge -s ours old

إذا كنت في الفرع

git merge -s recursive -X theirs B

تم اختباره على GIT الإصدار 1.7.8

عند دمج فرع الموضوع "B" في "A" باستخدام GIT دمج ، أحصل على بعض النزاعات. أعرف أن جميع الصراعات يمكن حلها باستخدام الإصدار في "B".

أنا على دراية بدمج git -لنا. لكن ما أريده هو شيء مثل دمج git>.

أفترض أنك قمت بإنشاء فرع من Master وأريد الآن الاندماج في Master ، مما تجاوز أي من الأشياء القديمة في Master. هذا بالضبط ما أردت فعله عندما صادفت هذا المنشور.

افعل بالضبط ما تريد القيام به ، باستثناء دمج الفرع الواحد في الآخر أولاً. لقد فعلت هذا للتو ، وقد عملت بشكل رائع.

git checkout Branch
git merge master -s ours

بعد ذلك ، يمكنك الخروج ماجستير ودمج فرعك فيه (سوف يذهب بسلاسة الآن):

git checkout master
git merge Branch

لإجراء دمج يتطلب بشكل صحيح حقًا فقط مدخلات من الفرع الذي تقوم بدمجه يمكنك القيام به

git merge --strategy=ours ref-to-be-merged

git diff --binary ref-to-be-merged | git apply --reverse --index

git commit --amend

لن يكون هناك أي صراعات في أي سيناريو أعرفه ، فلا يتعين عليك إنشاء فروع إضافية ، ويعمل مثل الاندماج العادي.

هذا لا يلعب بشكل جيد مع العارض الفرعي.

نرى إجابة جونيو هامانو على نطاق واسع: إذا كنت ستجاهل المحتوى الملتزم ، فما عليك سوى تجاهل الالتزامات ، أو على أي حال ، ابقها خارج التاريخ الرئيسي. لماذا تزعج الجميع في المستقبل رسائل القراءة من الالتزامات التي ليس لديها ما تقدمه؟

ولكن في بعض الأحيان هناك متطلبات إدارية ، أو ربما بعض الأسباب الأخرى. بالنسبة لتلك المواقف التي يتعين عليك فيها تسجيل الالتزامات التي لا تسهم شيئًا ، فأنت تريد:

(تحرير: واو ، هل تمكنت من الحصول على هذا الخطأ من قبل. هذا واحد يعمل.)

git update-ref HEAD $(
        git commit-tree -m 'completely superseding with branchB content' \
                        -p HEAD -p branchB    branchB:
)
git reset --hard

لماذا غير موجود؟

بينما أذكر في "أمر git لجعل فرع واحد مثل الآخر"كيفية المحاكاة git merge -s theirs, ، لاحظ أن Git 2.15 (الربع الرابع من عام 2017) أصبح الآن أكثر وضوحًا:

الوثائق ل"-X<option>"من أجل دمج كُتب بشكل مضلل لتوضيح ذلك"-s theirs"موجود، وهذا ليس هو الحال.

يرى ارتكاب c25d98b (25 سبتمبر 2017) بواسطة جونيو سي هامانو (gitster).
(تم الدمج بواسطة جونيو سي هامانو -- gitster -- في ارتكاب 4da3e23, ، 28 سبتمبر 2017)

استراتيجيات الدمج:تجنب الإشارة إلى ذلك "-s theirs"موجود

وصف -Xours خيار الدمج له ملاحظة قاتمة تخبر القراء بأنها مختلفة تمامًا عن -s oursوهو صحيح ، ولكن وصف -Xtheirs يتبعها يقول بلا مبالاة "هذا هو عكس ذلك ours"، إعطاء انطباع خاطئ بأن القراء بحاجة أيضًا إلى التحذير من أنه يختلف تمامًا عن -s theirs, ، وهو في الواقع غير موجود.

-Xtheirs هو خيار الاستراتيجية تطبق على استراتيجية العودية.وهذا يعني أن الإستراتيجية العودية سوف تستمر في دمج أي شيء يمكنها دمجه، وسوف تعود فقط إلى "theirs"المنطق في حالة الصراعات.

هذا النقاش حول مدى أهمية أ theirs تم إرجاع استراتيجية الدمج مؤخرًا في هذا سبتمبر.موضوع 2017.
إنه يعترف المواضيع القديمة (2008).

باختصار الحديث السابق يمكن تلخيصه في "لا نريد"-s theirs"لأنه يشجع سير العمل الخاطئ".

ويذكر الاسم المستعار:

mtheirs = !sh -c 'git merge -s ours --no-commit $1 && git read-tree -m -u $1' -

ويحاول ياروسلاف هالتشينكو مرة أخرى الدفاع عن هذه الاستراتيجية، لكن جونيو سي.يضيف هامانو:

السبب وراء عدم تماثل تاريخنا وتاريخهم هو أنك أنت وليس هم --- السيطرة على تاريخنا وملكيته وتاريخهم غير متماثل.

بمجرد أن تقرر أن تاريخهم هو الخط الرئيسي، فإنك تفضل التعامل مع خط التطوير الخاص بك كفرع جانبي وإجراء دمج في هذا الاتجاه، أي.الوالد الأول للدمج الناتج هو التزام بسجله والوالد الثاني هو آخر سيء في سجلك.لذلك سينتهي بك الأمر باستخدام "checkout their-history && merge -s ours your-history"للحفاظ على أول أمور معقولة.

وفي تلك المرحلة، استخدم "-s ours"لم يعد حلاً لعدم وجود"-s theirs".
وهو جزء مناسب من الدلالات المطلوبة، أي.من وجهة نظر خط التاريخ القانوني الباقي، فأنت تريد الحفاظ على ما فعله، وإبطال ما فعله خط التاريخ الآخر.

يستخدم هذا الشجرة القراءة أمر GIT Plumbing ، ولكنه يجعل من سير عمل أقصر.

git checkout <base-branch>

git merge --no-commit -s ours <their-branch>
git read-tree -u --reset <their-branch>
git commit

# Check your work!
git diff <their-branch>

سيؤدي ذلك إلى دمج NewBranch في القاعدة الحالية

git checkout <baseBranch> // this will checkout baseBranch
git merge -s ours <newBranch> // this will simple merge newBranch in baseBranch
git rm -rf . // this will remove all non references files from baseBranch (deleted in newBranch)
git checkout newBranch -- . //this will replace all conflicted files in baseBranch

أعتقد أن ما تريده بالفعل هو:

git checkout -B mergeBranch branchB
git merge -s ours branchA
git checkout branchA
git merge mergeBranch
git branch -D mergeBranch

هذا يبدو خرقاء ، ولكن يجب أن يعمل. الفكر الوحيد الذي لا يعجبني حقًا في هذا الحل هو أن تاريخ GIT سيكون مربكًا ... ولكن على الأقل سيتم الحفاظ على التاريخ تمامًا ولن تحتاج إلى القيام بشيء خاص للملفات المحذوفة.

المكافئ (الذي يحافظ على ترتيب الوالدين) إلى "دمج GIT -فرعهم"

قبل الاندماج:enter image description here

!!! تأكد من أنك في حالة نظيفة !!!

هل الدمج:

git commit-tree -m "take theirs" -p HEAD -p branchB 'branchB^{tree}'
git reset --hard 36daf519952 # is the output of the prev command

ماذا فعلنا؟ لقد أنشأنا التزامًا جديدًا بين الوالدين ولديهما و contnet من الالتزام هو BranchB - لهما

بعد الاندماج:enter image description here

أكثر دقة:

git commit-tree -m "take theirs" -p HEAD -p 'SOURCE^{commit}' 'SOURCE^{tree}'

أعطى هذا الجواب من قبل بول بلديج. لقد أخذت أوامره للتو وجعلت اسمًا مستعارًا للراحة.

قم بتحرير .gitConfig وأضف ما يلي:

[alias]
    mergetheirs = "!git merge -s ours \"$1\" && git branch temp_THEIRS && git reset --hard \"$1\" && git reset --soft temp_THEIRS && git commit --amend && git branch -D temp_THEIRS"

ثم يمكنك "Git Merge -s لهم" عن طريق الجري:

git checkout B (optional, just making sure we're on branch B)
git mergetheirs A

كنت بحاجة مؤخرًا إلى القيام بذلك لمستودعين منفصلين يشتركان في تاريخ مشترك. لقد بدأت مع:

  • Org/repository1 master
  • Org/repository2 master

أردت كل التغييرات من repository2 master ليتم تطبيقه على repository1 master, ، قبول جميع التغييرات التي سيجريها مستودع 2. من حيث GIT ، هذا ينبغي تكون استراتيجية تسمى -s theirs لكنه غير موجود. كن حذرا لأن -X theirs سمي كما تريد ما تريد ، لكنه كذلك ليس الشيء نفسه (حتى يقول ذلك في صفحة الرجل).

كانت الطريقة التي حللت بها هذا للذهاب إلى repository2 وجعل فرعًا جديدًا repo1-merge. في هذا الفرع ، ركضت git pull git@gitlab.com:Org/repository1 -s ours ويدمج بشكل جيد دون أي مشاكل. ثم أدفعه إلى جهاز التحكم عن بُعد.

ثم أعود إلى repository1 وجعل فرعًا جديدًا repo2-merge. في هذا الفرع ، أركض git pull git@gitlab.com:Org/repository2 repo1-merge والتي سوف تكتمل مع القضايا.

أخيرًا ، ستحتاج إما إلى إصدار طلب دمج في repository1 لجعله السيد الجديد ، أو مجرد الاحتفاظ به كفرع.

طريقة بسيطة وبديهية (في رأيي) من خطوتين للقيام بذلك هي

git checkout branchB .
git commit -m "Picked up the content from branchB"

تليها

git merge -s ours branchB

(الذي يمثل الفرعين كما اندمج)

العيب الوحيد هو أنه لا يزيل الملفات التي تم حذفها في فرع من فرعك الحالي. سيظهر فرق بسيط بين الفرعين بعد ذلك ما إذا كان هناك أي ملفات من هذا القبيل.

يوضح هذا النهج أيضًا من سجل المراجعة بعد ذلك ما تم القيام به - وما المقصود.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top