Существует ли “их” версия "git merge -s ours”?

StackOverflow https://stackoverflow.com/questions/173919

  •  05-07-2019
  •  | 
  •  

Вопрос

При объединении ветви темы "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, выполнило удаление.

Исправить это несложно.Просто беги git rm с именем всех файлов, которые были удалены:

git rm {DELETED-FILE-NAME}

После этого, -X theirs должно сработать так, как ожидалось.

Конечно, выполняя фактическое удаление с помощью git rm командование в первую очередь предотвратит возникновение конфликта.


Примечание:Также существует вариант с более длинной формой.Чтобы использовать его, замените:

-X theirs

с:

--strategy-option=theirs

Другие советы

Возможное и проверенное решение для слияния BranchB в наш извлеченный BranchA:

# 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 их ответвлениеB .

Более старые версии git позволяли вам использовать " их " стратегия слияния:

git pull --strategy=theirs remote_branch

Но с тех пор это было удалено, как объясняется в этом сообщении Джунио Хамано (сопровождающий Git). Как отмечено в ссылке, вместо этого вы должны сделать это:

git fetch origin
git reset --hard origin

Остерегайтесь, однако, что это отличается от фактического слияния. Ваше решение - это, вероятно, вариант, который вы действительно ищете.

С тех пор я использовал ответ от Поля Пладийса. Я обнаружил, что вы можете сделать "нормальный" слияние, возникают конфликты, так что вы делаете

git checkout --theirs <file>

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

git merge <branch> -s theirs

В любом случае, усилия больше, чем это было бы с помощью стратегии слияния! (Это было протестировано с 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.Это то , что , например, Ответ Гэндальфа 458 делает.

Используйте содержимое только из 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

Если вы находитесь на ветке A, сделайте:

git merge -s recursive -X theirs B

Протестировано на git версии 1.7.8

  

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

     

Я знаю, что Git Merge - наш. Но я хочу что-то вроде git merge > -s их.

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

Делайте именно то, что вы хотите, за исключением того, что сначала объедините одну ветвь с другой. Я только что сделал это, и это сработало отлично.

git checkout Branch
git merge master -s ours

Затем извлеките мастер и объедините в нем свою ветку (теперь все пройдет гладко):

git checkout master
git merge Branch

Чтобы действительно правильно выполнить слияние, которое требует только ввода из ветви, которую вы объединяете, вы можете сделать

git merge --strategy = наш ref-to-be-merged

git diff - двоичный 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 (4 квартал 2017) теперь понятнее:

Документация для '-X<option>' for merges был введен в заблуждение написан, чтобы предположить, что "-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>

Это объединит ваш новый филиал с существующим базовым филиалом

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 merge -это их филиал'

Перед слиянием: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}'

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

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

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, принимая все изменения, которые внесет repository2.С точки зрения 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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top