Виберіть стратегію злиття Git для конкретних файлів ("наші", "мої", "їхні")


207

Я в середині звільнення після git pull --rebase. У мене є кілька файлів, у яких є конфлікти злиття. Як я можу прийняти "їх" зміни або "мої" зміни для конкретних файлів?

$ git status
# Not currently on any branch.
# You are currently rebasing.
#   (fix conflicts and then run "git rebase --continue")
#   (use "git rebase --skip" to skip this patch)
#   (use "git rebase --abort" to check out the original branch)
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:  CorrectlyMergedFile
#
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add <file>..." to mark resolution)
#
#       both modified: FileWhereIWantToAcceptTheirChanges
#       both modified: FileWhereIWantToAcceptMyChanges

Зазвичай я просто відкриваю файл або інструмент злиття і вручну приймаю всі "їх" або "мої" зміни. Однак я підозрюю, що мені не вистачає зручної команди git.

Також зауважте, що я можу вибрати стратегію злиття для кожного файлу лише тоді, коли я побачу, які файли потрапляють у конфлікти, можливо, що таке конфлікти.


@AbeVoelker Я не думаю, що це вирішує мою проблему. Я хочу вибрати стратегію злиття для конкретних файлів. Також зауважте, що я буду знати лише те, яку стратегію злиття використовувати, коли я перебуваю у своїй базі даних та бачу, які файли потрапили в конфлікти та які конфлікти.
Стівен Векслер

Я редагував це питання більш загальний: stackoverflow.com/questions/278081 / ... . Може, ми можемо закрити це питання як дублікат цього? Чи підходить це?

@TheShadow Це мені здається розумним.
Стівен Векслер

Я не був впевнений, чи доречно змінити назву іншого питання на те, що я зробив, тому що я взяв участь у вирішенні бінарних файлів. Я відновив інше питання до того, що було раніше, тож це поточне питання все ще додає значення.

Відповіді:


251

Для кожного отриманого конфліктного файлу ви можете вказати

git checkout --ours -- <paths>
# or
git checkout --theirs -- <paths>

Від git checkoutдок

git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...

--ours
--theirs
Перевіряючи шляхи з індексу, перевірте стадію №2 ( ours) або №3 ( theirs) для безперебійних шляхів.

Індекс може містити незаряджені записи через попереднє невдале злиття. За замовчуванням, якщо ви спробуєте перевірити такий запис з індексу, операція оформлення каси закінчиться невдачею, і нічого не буде перевірено. Використання -fбуде ігнорувати ці незареєстровані записи. Вміст з певної сторони злиття можна перевірити з індексу за допомогою --oursабо --theirs. З -m, зміни, внесені до файлу робочого дерева, можуть бути відхилені, щоб відновити вихідний конфліктний результат злиття.


9
Чи можна прийняти ваші файли для всіх файлів, які залишились увімкненими?
aslakjo

41
@aslakjo git rebase -s recursive -X <ours/theirs>або git merge -s recursive -X <ours/theirs>. Майте на увазі, що для відновлення "наші" та "їхні" повертаються до того, що вони є під час злиття. Можливо, ви також можете просто використовувати файл / оболонку, наприклад git checkout --theirs -- *.txt.

2
Велике спасибі, @Cupcake, несподіване перевертання з ours/theirsвикористанням бази даних зводило мене з розуму !! (Має сенс, що я думаю про те, як насправді працює ребаза, але зовсім не інтуїтивно зрозуміла.)
Ден Ленскі,

2
@DanLenski Rebase взагалі - це справді хитрий інструмент, який люди спочатку можуть зрозуміти, але як тільки ви зрозумієте, як це працює, ви можете робити з ним усілякі справді потужні речі.

1
@VincentSels насправді вам потрібно замаскувати символ *, інакше оболонка спробує розгорнути його. тож у вашому випадку git checkout --outs -- "**/*.csproj"буде робити те, що ви маєте на увазі. Те саме стосується, наприклад, для git lfs track "*.jpg". Якщо у вашому CWD є деякі jpg-файли, без лапок, відслідковуватимуться лише вони.
eFloh

117

Навіть незважаючи на те, що на це запитання дано відповідь, надаючи приклад того, що означає "їхнє" та "наше" у разі відновлення git відновлення та злиття. Дивіться це посилання

Git Rebase
theirs - це фактично поточна галузь у випадку ребазування . Отже, наведений нижче набір команд фактично приймає ваші поточні зміни гілки через віддалену гілку.

# see current branch
$ git branch
... 
* branch-a
# rebase preferring current branch changes during conflicts
$ git rebase -X theirs branch-b

Git Merge
Для злиття сенс theirsі oursобернено. Отже, щоб отримати той самий ефект під час злиття , тобто збережіть ваші поточні зміни гілки ( ours) над об'єднаною віддаленою гілкою ( theirs).

# assuming branch-a is our current version
$ git merge -X ours branch-b  # <- ours: branch-a, theirs: branch-b

2
ну це досить важлива відмінність! дякую за уточнення.
вербозез

26

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

Якщо замість цього ви хочете здійснити тристороннє злиття файлу і вирішити лише конфліктні файли, використовуючи --ours|--theirs, зберігаючи на місці неконфліктні описи з обох сторін, можливо, ви захочете вдатися до цього git merge-file; див. деталі у цій відповіді .


1
Щодо "безконфліктних змін", які будуть втрачені - це стосується лише тих файлів, де в певному рядку в одному і тому ж файлі є безконфліктні зміни, або всіх змін з усіх файлів у вирівняних історіях?
ktamlyn

2
@ktamlyn під "безконфліктними змінами" я мав на увазі зміни в тому самому файлі. Наприклад, example.txtу oursверсії є дві змінені частини (частини) , одна суперечлива (також змінена в theirsредакції), інша - безконфліктна. Якщо ви зробите git checkout --theirs example.txtце, він просто сліпо прочитає весь файл при theirsперегляді, і безконфліктна частина розімкнеться.
jakub.g

1
Дякую! Це було для мене необхідним уточненням, хоча "зміни в одному файлі" мають найбільш сенс у цьому контексті.
ktamlyn

Це має бути прийнятою відповіддю, ну хоча вона насправді не дає відповіді, але вказує на важливе питання в іншому запропонованому рішенні.
tomasyany

1
Якщо ви хочете повернутися до оригінального конфліктованого файлу, можете запустити git checkout --merge <path>.
Ендрю Кітон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.