Вирішіть конфлікти злиття Git на користь їх змін під час тяги


1225

Як вирішити конфлікт git merge на користь витягнутих змін?

В основному мені потрібно видалити всі суперечливі зміни з робочого дерева, не git mergetoolпроходячи всі конфлікти, зберігаючи всі безконфліктні зміни. Переважно робити це під час витягування, а не після цього.


3
можливий дублікат git merge -s


3
@DanDascalescu Прийнята відповідь там не відповідає на ці запитання, тому однозначно це не дублікат. Плюс до того, що інше питання є досить неоднозначним: дуже важко сказати, що задається. Загалом я не можу з вами погодитися. Що ви на це вказуєте?
sanmai

2
@sanmai У вас є дві відповіді - і ви прийняли одну з них. Чи можете ви краще пояснити, чого ви очікуєте у відповіді і скільки деталей ви хочете тут?
Едвард Томсон,

2
@EdwardThomson добре, насправді я думав дати цю репутацію першою відповіддю, але якщо ви запитаєте, я можу зачекати і побачити, чи з’явиться краща відповідь
sanmai

Відповіді:


1217
git pull -s recursive -X theirs <remoterepo or other repo>

Або просто для сховища за замовчуванням:

git pull -X theirs

Якщо ви вже в конфліктному стані ...

git checkout --theirs path/to/file

40
Зауважте, що -s recursiveтут зайве, оскільки це стратегія злиття за замовчуванням. Таким чином, ви можете спростити його git pull -X theirs, що в основному еквівалентно git pull --strategy-option theirs.

5
Якщо я це роблю, я опиняюся назад у MERGINGштаті. Я можу потім git merge --abortспробувати ще раз, але щоразу закінчуюся злиттям. … Я знаю, що на мою верхню течію була спрямована база даних, тож, можливо, це викликає це?
Benjohn

22
Будьте обережні git checkout --theirs path/to/file. Використовували його під час ребазування та отримували несподівані результати. Знайдено пояснення в документі: Зауважте, що під час git rebase та git pull --rebase, наше та їх може з’явитися заміненим; --ours дає версію з гілки, на яку зміни переносяться, тоді як --thers дає версію з гілки, яка містить вашу роботу, яка перезавантажується.
Вук Джапіч

10
Зауважте, що на git checkout --theirs/--ours pathсторінці man вказано, що вона працює для безперервних шляхів . Отже, якщо конфлікту на шляху не було, то вже об'єднана ця команда нічого не зробить. Це може виникнути проблема, коли ви хочете, наприклад, "їхню" версію цілої підпапки. Тож у такому випадку було б безпечніше робити git checkout MERGE_HEAD pathабо використовувати хеш-код.
fsw

4
git pull -X theirsстворює комісію злиття, якщо виникають конфлікти (наприклад, якщо інший комітер біг git push -fдо віддаленого). Якщо ви не хочете об'єднати комісії, запустіть замість цього git fetch && git reset --hard origin/master.
Дан Даскалеску

985

Ви можете використовувати рекурсивний варіант "їхньої" стратегії :

git merge --strategy-option theirs

Від людини :

ours
    This option forces conflicting hunks to be auto-resolved cleanly by 
    favoring our version. Changes from the other tree that do not 
    conflict with our side are reflected to the merge result.

    This should not be confused with the ours merge strategy, which does 
    not even look at what the other tree contains at all. It discards 
    everything the other tree did, declaring our history contains all that
    happened in it.

theirs
    This is opposite of ours.

Зауважте: як говорить сторінка man, варіант "нашої" стратегії злиття сильно відрізняється від "нашої" стратегії злиття .


Ось більш детальне пояснення: lostechies.com/joshuaflanagan/2010/01/29/…
mPrinC

227
Також git checkout --theirsоперувати єдиним конфліктуючим файлом
dvd

48
Це не працює, якщо ви вже перебуваєте в стані вирішення конфлікту. У такому випадку я вважаю, що найкращий спосіб вирішити - це git checkout <ref to theirs> -- the/conflicted.file; а потім git addїх зміни.
ThorSummoner

54
@ThorSummoner У такому випадку є перевірка git - їх шлях / з / файл. Таким чином, вам не потрібно вручну шукати правильний хеш.
Іке

8
@Ikke Це, в основному, має бути власна відповідь (і прийнята відповідь на це), якщо ви запитаєте мене.
ThorSummoner

473

Якщо ви вже перебуваєте в конфліктному стані, і хочете просто прийняти всі їхні дії:

git checkout --theirs .
git add .

Якщо ви хочете зробити навпаки:

git checkout --ours .
git add .

Це досить драстично, тому переконайтеся, що ви дійсно хочете стерти все таким чином, перш ніж це робити.


47
або не використовуйте .та вказуйте файли замість крапки, яку ви хочете отримати. менш "різко" та саме те, що ви хочете зробити, імовірно.
manroe

10
це не працює, якщо файл видалено з іншої гілки: '<file>' не має своєї версії
Japster24

3
Коли б я міг би подати більше, я б продовжував повертатися до цієї відповіді.
tarikki

6
Використовуйте git add -uнатомість, щоб пропустити файли, які не знаходяться під контролем версій.
Судіпта Басак

3
Гіпотетичний випадок, три зміни у файлі, одна суперечлива, дві без конфлікту, чи застосувало б це рішення неконфліктні зміни та вирішить суперечливі зміни до наших? Або знадобиться лише наша версія, ігноруючи не суперечливі зміни від їхніх?
педромарс

222

Гаразд, так, сформулюйте сценарій, в якому я був саме:

Ви намагаєтесь merge, а може бути cherry-pick, і вас зупинили

$ git cherry-pick 1023e24
error: could not apply 1023e24... [Commit Message]
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

Тепер ви переглядаєте конфліктований файл і дійсно не хочете зберігати свої зміни. У моєму випадку вище файл конфліктував лише на новому рядку, який мій IDE автоматично додав. Щоб скасувати зміни та прийняти їх, найпростіший спосіб:

git checkout --theirs path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

Зворотне це (щоб замінити вхідну версію на вашу версію) є

git checkout --ours path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

Дивно, але я не міг знайти цю відповідь дуже легко в мережі.


15
Зауважте, що якщо один виконує git statusміж checkoutі add, файл все одно відображається як "обидва змінені".
єпископ

Чи знаєте ви, чи існує спосіб зробити це для всіх файлів, які знаходяться в конфліктному стані? Якщо так, то було б приємним продовженням вашої відповіді.
Дрю Ноакс

2
Я роблю це: git reset --hard а потім git pull [remote server name] [branch name] -Xtheirs(скасовує злиття, потім витягує новий матеріал поверх моїх речей) - не впевнений, чи це те, що ви хочете.
ssaltman

38

Ці git pull -X theirsвідповіді можуть створити потворне злиття зробити, або видати

помилка: Ваші локальні зміни до таких файлів будуть перезаписані об'єднанням:

Якщо ви хочете просто проігнорувати будь-які локальні модифікації файлів із репо, наприклад, на клієнті, який завжди повинен бути дзеркалом походження, запустіть це (замініть masterпотрібну гілку):

git fetch && git reset --hard origin/master

Як це працює? git fetchробить, git pullале без злиття . Тоді git reset --hardзмушує ваше робоче дерево відповідати останньому комітету. Усі ваші локальні зміни до файлів репо будуть відмінені , але нові локальні файли залишаться в спокої.


1
+1 - git fetch && git reset --hard {remote}/{branch}було тим, що вирішило мою проблему. Мені потрібно було повністю вирвати власні зміни на користь "їхнього" стану гілки, але git pull -X theirsзадихнувся від деяких переміщених / перейменованих файлів. Дякую!
Івайло Славов

22

Після злиття git, якщо у вас виникли конфлікти, і ви хочете або свої, або їхні

git checkout --theirs .
git checkout --ours .

Як би я це зробив на основі конфліктної частини? Вищезазначене працює на рівні файлу, викидаючи будь-які неконфліктні фрагменти, які можуть мати конфліктний файл.
Яні

21

Щоб вирішити всі конфлікти з версією в певній галузі:

git diff --name-only --diff-filter=U | xargs git checkout ${branchName}

Отже, якщо ви вже перебуваєте в стані злиття, і хочете зберегти головну версію конфліктуючих файлів:

git diff --name-only --diff-filter=U | xargs git checkout master

А для людей на вікнах, які не мають доступу до труб xargs, як це перекладається?
цемер

Хіба це не пропустило б ваші зміни повністю? Навіть ті, які не перебувають у конфліктному стані?
Валентин Хайніц

Це я і закінчила. На жаль, в подальшому вимагає або git cherry-pick --continue або в git commit --allow-emptyкоманді , щоб зробити ці зміни, і , здається , немає ніякої системи , за якої потрібно команда, яка робить автоматизації цього біль. Зараз я це вирішую, перевіряючи наявність .git/COMMIT_EDITMSGфайлу, але це здається хитким і крихким, і я ще не впевнений, що це завжди працює.
Конрад Рудольф

Це добре, це означає, що якщо ви вручну вирішите деякі (і зробите git add), тоді ви зможете масово вирішити решту за допомогою цього. git checkout --ours/ git checkout --theirsтеж корисний.
rcoup

18

Зауважте, що іноді це не вийде :

git checkout - ваш шлях / до / файл

або

git checkout - їх шлях / до / файл

Я зробив це замість цього, вважаючи, що HEAD - це наше, а MERGE_HEAD - їхнє

git checkout HEAD -- path/to/file

або:

git checkout MERGE_HEAD -- path/to/file

Після того як ми це зробимо і нам добре:

git add .

Якщо ви хочете зрозуміти більше, дивіться чудовий пост торека тут: git checkout --ours не видаляє файли зі списку файлів, що не ввімкнули


12

Код VS (інтегрований Git) IDE користувачів:

Якщо ви хочете прийняти всі вхідні зміни в конфліктному файлі, виконайте наступні дії.

1. Go to command palette - Ctrl + Shift + P
2. Select the option - Merge Conflict: Accept All Incoming

Аналогічно можна зробити і для інших варіантів, таких як Прийняти всі обидва, Прийняти всі поточні тощо,


2
Це, здається, працює лише для одного файлу, але не для всіх файлів із конфліктами.
Yoryo

1

У мене була давня next-versionгілка з тоннами видалень файлів, які змінилися develop, файли, додані в різних місцях обох гілок тощо.

Я хотів взяти весь вміст next-versionгілки develop, все в одному величезному об'єднанні.

Поєднання перерахованих вище команд, які працювали для мене:

git merge -X theirs next-version
# lots of files left that were modified on develop but deleted on next-version
git checkout next-version .
# files removed, now add the deletions to the commit
git add .
# still have files that were added on develop; in my case they are all in web/
git rm -r web

Не нова відповідь, просто комбінування бітів з багатьма відповідями, частково для того, щоб запевнити, що вам можуть знадобитися всі ці відповіді.


1

Якщо ви вже перебуваєте в конфліктному стані і не хочете перевіряти шлях по черзі. Ви можете спробувати

git merge --abort
git pull -X theirs

-1

від https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging

Це в основному зробить фальшиве злиття. Він запише нову комісію злиття з обома гілками як батьки, але навіть не буде дивитись на гілку, в яку ви зливаєтеся. Він просто запише в результаті об'єднання точного коду у вашій поточній гілці.

$ git merge -s ours mundo

Об’єднання, здійснене за допомогою нашої стратегії.

$ git diff HEAD HEAD~

Видно, що різниці між галуззю, на якій ми були, та результатом злиття немає.

Це часто може бути корисним для того, щоб в основному обдурити Git думати, що гілка вже об'єднана при злитті пізніше. Наприклад, скажіть, що ви розгалужили гілку випуску і виконали певну роботу над нею, яку ви хочете в якийсь момент об'єднати назад у свою головну гілку. Тим часом деяку помилку на програмі master потрібно підтримати у відділенні релізу. Ви можете об'єднати гілку помилок у гілку випуску, а також об'єднати -як наша ж гілка у вашу головну гілку (навіть якщо виправлення вже є), тож коли ви згодом знову з’єднаєте гілку випуску, конфлікту з виправленням не буде.

Ситуація, яку я вважаю корисною, якщо хочу, щоб майстер відображав зміни нової галузі теми. Я помітив, що -Xtheirs не зливаються без конфліктів за певних обставин ... наприклад

$ git merge -Xtheirs topicFoo 

CONFLICT (modify/delete): js/search.js deleted in HEAD and modified in topicFoo. Version topicFoo of js/search.js left in tree.

У цьому випадку рішення, яке я знайшов, було

$ git checkout topicFoo

від topicFoo, спочатку об'єднавшись у master за допомогою нашої стратегії, це створить фальшивий фіксатор, який є лише станом topicFoo. $ git merge - наш господар

перевірте створене об'єднання об'єднань

$ git log

тепер оформити головну гілку

$ git checkout master

об'єднайте гілку теми назад, але на цей раз використовуйте рекурсивну стратегію -Xtheirs, тепер це представить вам головну гілку зі станом topicFoo.

$ git merge -X theirs topicFoo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.