Есть "их" версия "git merge -s ours"? - PullRequest
767 голосов
/ 06 октября 2008

При объединении ветки темы "B" в "A" с использованием git merge возникают конфликты. Я знаю, что все конфликты могут быть решены с помощью версии в "B".

Мне известно о git merge -s ours. Но я хочу что-то вроде git merge -s theirs.

Почему его не существует? Как я могу достичь того же результата после конфликтующего слияния с существующими командами git? (git checkout каждый необъединенный файл из B)

ОБНОВЛЕНИЕ: «Решение» простого отказа от чего-либо из ветви A (точка фиксации слияния до версии дерева B) не является тем, что я ищу.

Ответы [ 18 ]

2 голосов
/ 14 октября 2017

Почему его не существует?

Хотя я упоминаю в " команде git для создания одной ветви как другой ", как имитировать git merge -s theirs, учтите, что Git 2.15 (Q4 2017) теперь более понятен:

Документация для '-X<option>' для слияний вводит в заблуждение написано, чтобы предположить, что "-s theirs" существует, а это не так.

См. коммит c25d98b (25 сентября 2017 г.) от Джунио С. Хамано (gitster) .
(Объединено с Junio ​​C Hamano - 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».
Это правильная часть желаемой семантики, то есть с точки зрения сохранившейся линии канонической истории, вы хотите сохранить то, что она сделала, сводя на нет то, что сделала другая строка истории .

2 голосов
/ 22 апреля 2015

Этот использует дерево чтения команды 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>
0 голосов
/ 30 мая 2019

Этот ответ дал Пол Пладийс. Я просто взял его команды и сделал псевдоним для удобства.

Отредактируйте ваш .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 -sss A", запустив:

git checkout B (optional, just making sure we're on branch B)
git mergetheirs A
0 голосов
/ 05 октября 2018

Простой и интуитивно понятный (на мой взгляд) двухэтапный способ сделать это

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

с последующим

git merge -s ours branchB

(который отмечает две ветви как объединенные)

Единственным недостатком является то, что он не удаляет файлы, которые были удалены в BranchB из вашей текущей ветви. После этого простой diff между двумя ветками покажет, есть ли такие файлы.

Этот подход также дает понять из журнала изменений после этого, что было сделано - и что было задумано.

0 голосов
/ 14 мая 2018

Эквивалент (сохраняющий родительский порядок) для 'git merge -s их ветвь B'

До слияния: 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

Что мы сделали? Мы создали новый коммит, у которого два родителя - наш и их, а коннект коммита - BranchB - их

После слияния: enter image description here

Точнее:

git commit-tree -m "take theirs" -p HEAD -p 'SOURCE^{commit}' 'SOURCE^{tree}'
0 голосов
/ 27 марта 2017

Мне только что нужно было сделать это для двух отдельных репозиториев, которые имеют общую историю. Я начал с:

  • 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, чтобы сделать его новым мастером, либо просто сохранить его как ветвь.

0 голосов
/ 31 августа 2016

Я думаю, что вы на самом деле хотите:

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

Это кажется неуклюжим, но должно работать. Единственное, что мне действительно не нравится в этом решении, это то, что история git будет сбивать с толку ... Но по крайней мере история будет полностью сохранена, и вам не нужно будет делать что-то особенное для удаленных файлов.

0 голосов
/ 28 января 2013

Это объединит вашу новую ветку с существующей базовой веткой

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
...