هل هناك نسخة "خاصة بهم" من "git merge -s Ours"؟
سؤال
عند دمج فرع الموضوع "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 -فرعهم"
!!! تأكد من أنك في حالة نظيفة !!!
هل الدمج:
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 - لهما
أكثر دقة:
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
(الذي يمثل الفرعين كما اندمج)
العيب الوحيد هو أنه لا يزيل الملفات التي تم حذفها في فرع من فرعك الحالي. سيظهر فرق بسيط بين الفرعين بعد ذلك ما إذا كان هناك أي ملفات من هذا القبيل.
يوضح هذا النهج أيضًا من سجل المراجعة بعد ذلك ما تم القيام به - وما المقصود.