Есть ли "их" версия "git merge-s ours"?

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

Я в курсе git merge -s ours. Но то, что я хочу, это что-то вроде git merge -s theirs.

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

UPDATE: "решение" просто отбросить что-либо из ветви A (the merge commit point to B версия дерева) - это не то, что я ищу.

18 ответов


добавить до theirs. Например:

git checkout branchA
git merge -X theirs branchB

все будет сливаться желаемым образом.

единственное, что я видел, вызывает проблемы, если файлы были удалены из branchB. Они появляются как конфликты, если что-то другое, чем git, сделало удаление.

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

git rm {DELETED-FILE-NAME}

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

Of конечно, делать фактическое удаление с 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

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

git fetch origin
git reset --hard origin

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


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

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. Это то, что например 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

это Павел Pladijs это делает (не требуя временной ветви).


Я решил свою проблему, используя

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 merge я получаю некоторые конфликты. Я >знаю, что все конфликты могут быть решены с помощью версии "Б".

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

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

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

git checkout Branch
git merge master -s ours

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

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

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

это не играет хорошо с подмодулями, однако.


посмотреть широко цитируемый ответ Хунио Хамано: Если вы собираетесь отбросить зафиксированный контент, просто отбросьте фиксации или, по крайней мере, держите его вне основной истории. Зачем беспокоить всех в будущем, читая сообщения фиксации от коммитов, которым нечего предложить?

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

(edit: wow, мне удалось получить это неправильно раньше. Этот работает.)

git update-ref HEAD $(
        git commit-tree -m 'completely superseding with branchB content' \
                        -p HEAD -p branchB    branchB:
)
git reset --hard

этот использует команду git plumbing read-tree, но делает более короткий общий рабочий процесс.

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

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

посмотреть совершить c25d98b (25 Sep 2017) by Junio C Hamano (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  && git read-tree -m -u ' -

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

как только вы решите, что их история является основной линией, вы предпочтете рассматривать свою линию развития как боковую ветвь и сделать слияние в этом направлении, т. е. первый родитель полученного слияния является фиксацией на их истории, а второй родитель-последним плохая история. Таким образом, вы в конечном итоге используете "checkout their-history && merge -s ours your-history" в держите первого родителя разумным.

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


это объединит ваш newBranch в существующий baseBranch

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 будет запутанной... Но, по крайней мере, история будет полностью сохранена, и вам не нужно будет делать что-то особенное для удаленных файлов.


обновление

хотя второй ответ отвечает на исходный вопрос OP, он не отражает обновленного намерения вопроса OP.


то, что вы ищете не наоборот


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

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

следовал по

git merge -s ours branchB

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

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

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


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

  • 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 merge-s theirs branchB"

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