У меня есть ветка, demo
которую мне нужно объединить с master
веткой. Я могу получить желаемый результат с помощью следующих команд:
git pull origin demo
git checkout master
git pull origin master
git merge demo
git push origin master
Меня беспокоит только то, что если есть какие-либо проблемы слияния , я хочу сказать git
перезаписать изменения в master
ветке, не давая мне приглашения на слияние. Таким образом, в основном изменения в demo
ветке должны автоматически перезаписывать изменения в master
ветке.
Я посмотрел вокруг, есть несколько вариантов, но я не хочу рисковать слиянием.
git push -f origin master
-f
параметр сmerge
командой, а не сpush
командойОтветы:
На самом деле это не связано с этим ответом, но я бы отказался от него
git pull
, за которымgit fetch
следуетgit merge
. Вы выполняете три слияния, которые заставят ваш Git запустить три операции выборки, когда вам достаточно одной выборки. Отсюда:Контроль самого сложного слияния
Самое интересное здесь
git merge -X theirs
. Как заметил root545 ,-X
параметры передаются стратегии слияния, и какrecursive
стратегия по умолчанию , так и альтернативнаяresolve
стратегия принимают-X ours
или-X theirs
(то или иное, но не оба). Однако, чтобы понять, что они делают, вам нужно знать, как Git находит и обрабатывает конфликты слияния .Конфликт слияния может возникнуть в каком-то файле 1, если базовая версия отличается как от текущей (также называемой локальной, HEAD или
--ours
) версии, так и от другой (также называемой удаленной или--theirs
) версии того же файла. То есть слияние выявило три ревизии (три коммита): базовую, нашу и их. «Базовая» версия взята из базы слияния между нашей фиксацией и их фиксацией, как показано на графике фиксации (для получения дополнительной информации см. Другие сообщения StackOverflow). Затем Git обнаружил два набора изменений: «что мы сделали» и «что они сделали». Эти изменения (как правило) находятся построчно, чисто текстовымиоснование. Git не имеет реального понимания содержимого файлов; это просто сравнение каждой строки текста.Эти изменения вы видите на
git diff
выходе, и, как всегда, они имеют контекст . Возможно, что то, что мы изменили, находится в разных строках от того, что они изменили, так что кажется, что изменения не будут конфликтовать, но контекст также изменился (например, из-за того, что наше изменение было близко к верху или низу файла, так что файл в нашей версии закончился, но в их они также добавили больше текста вверху или внизу).Если изменения происходят на разных линиях, например, мы изменяем
color
кcolour
строке 17 и они изменяютсяfred
вbarney
на линии 71-то нет никакого конфликта: Git просто принимает оба изменения. Если изменения происходят в тех же строках, но являются идентичными изменениями, Git берет одну копию изменения. Только если изменения находятся в тех же строках, но представляют собой разные изменения, или этот особый случай мешающего контекста, вы получаете конфликт изменения / изменения.Параметры
-X ours
и-X theirs
сообщают Git, как разрешить этот конфликт, выбирая только одно из двух изменений: наше или их. Поскольку вы сказали, что объединяетеdemo
(их) сmaster
(нашим) и хотите изменений отdemo
, вы бы захотели-X theirs
.Однако слепое применение
-X
опасно. Тот факт, что наши изменения не противоречили построчно, не означает, что наши изменения фактически не конфликтуют! Один классический пример встречается в языках с объявлениями переменных. В базовой версии может быть объявлена неиспользуемая переменная:В нашей версии мы удаляем неиспользуемую переменную, чтобы отключить предупреждение компилятора, а в их версии они добавляют цикл на несколько строк позже, используя его
i
как счетчик цикла. Если мы объединим два изменения, полученный код больше не будет компилироваться. Этот-X
вариант здесь не поможет, поскольку изменения касаются разных строк .Если у вас есть автоматизированный набор тестов, самое важное - запустить тесты после слияния. Вы можете сделать это после фиксации и при необходимости исправить позже; или вы можете сделать это перед фиксацией, добавив
--no-commit
вgit merge
команду. Мы оставим детали для других публикаций.1 Вы также можете получить конфликты в отношении операций «на уровне файла», например, возможно, мы исправим написание слова в файле (так, чтобы у нас было изменение), и они удаляют весь файл (чтобы у них был удалять). Git не разрешит эти конфликты самостоятельно, независимо от
-X
аргументов.Выполнение меньшего количества слияний и / или более умных слияний и / или использование перебазирования
В обеих последовательностях команд есть три слияния. Первый - внести
origin/demo
в локальныйdemo
(ваши варианты использования,git pull
которые, если ваш Git очень старый, не смогут обновиться,origin/demo
но дадут тот же конечный результат). Во - вторых , чтобы принестиorigin/master
вmaster
.Мне не понятно, кто обновляет
demo
и / илиmaster
. Если вы пишете свой собственный код в своейdemo
ветке, а другие пишут код и отправляют его вdemo
веткуorigin
, тогда это слияние на первом этапе может иметь конфликты или производить настоящее слияние. Чаще всего для объединения работы лучше использовать rebase, чем merge (правда, это вопрос вкуса и мнения). Если это так, вы можете использоватьgit rebase
вместо него. С другой стороны, если вы никогда не делать какие - либо из ваших собственных фиксаций наdemo
, вы даже не нужно вdemo
отрасли. В качестве альтернативы, если вы хотите автоматизировать большую часть этого, но при этом иметь возможность тщательно проверять, есть ли коммиты, сделанные вами и другими, вы можете использоватьgit merge --ff-only origin/demo
: это переместит вас вперед,demo
чтобы соответствовать обновленному,origin/demo
если это возможно, и просто полностью потерпит неудачу, если нет (в этот момент вы можете проверить два набора изменений и выбрать реальное слияние или перебазирование, если это необходимо).Эта же логика применима и к
master
, хотя вы делаете слияние наmaster
, так что вы определенно нужныmaster
. Однако еще более вероятно, что вы захотите, чтобы слияние завершилось неудачно, если оно не может быть выполнено как быстрое вперед без слияния, так что это, вероятно, также должно бытьgit merge --ff-only origin/master
.Допустим, вы никогда не выполняете свои собственные коммиты
demo
. В этом случае мы можем полностью отказаться от названияdemo
:Если будут делать свои собственные
demo
ветви фиксаций, это не полезно; вы также можете сохранить существующее слияние (но, возможно, добавить в--ff-only
зависимости от того, какое поведение вы хотите), или переключить его на выполнение перебазирования. Обратите внимание, что все три метода могут завершиться неудачно: слияние может завершиться сбоем с конфликтом, слияние с--ff-only
может не иметь возможности быстрой перемотки вперед, а перебазирование может завершиться сбоем с конфликтом (перебазирование, по сути, работает с помощью коммитов выбора вишни , которые используют слияние машины и, следовательно, может возникнуть конфликт слияния).источник
У меня была аналогичная проблема, когда мне нужно было эффективно заменить любой файл, в котором были изменения / конфликты, с другой веткой.
Я нашел решение - использовать
git merge -s ours branch
.Учтите, что вариант есть,
-s
а нет-X
.-s
обозначает использованиеours
в качестве стратегии слияния верхнего уровня,-X
будет применять этуours
опцию кrecursive
стратегии слияния, чего я (или мы) не хочу в данном случае.Шаги, где
oldbranch
находится ветка, которую вы хотите перезаписатьnewbranch
.git checkout newbranch
проверяет ветку, которую вы хотите сохранитьgit merge -s ours oldbranch
сливается со старой веткой, но сохраняет все наши файлы.git checkout oldbranch
проверяет ветку, которую вы хотите перезаписатьget merge newbranch
сливается в новую ветку, перезаписывая старую веткуисточник
Этот подход слияния добавит один коммит, поверх
master
которого вставит все, что естьfeature
, без жалоб на конфликты или другую чушь.Прежде чем прикоснуться к чему-либо
git stash git status # if anything shows up here, move it to your desktop
Теперь подготовим мастера
git checkout master git pull # if there is a problem in this step, it is outside the scope of this answer
Получить
feature
все одетыПойти на убийство
источник
Changes from the other tree that do not conflict with our side are reflected in the merge result
. У меня это не сработало, так как в моей ветке были чисто слитные коммиты, которые перезаписывались. Есть ли другой способ?Вы можете попробовать «наш» вариант в git merge,
источник
demo
версия была предпочтительнее, даже если он сливается сmaster
. Также есть-X theirs
, но неясно, чего действительно хочет ОП.ours
происходит при использовании на бэкэнде с-s
опцией. При использованииours
with-X
: отбрасывает все, что делало другое дерево, объявляя, что наша история содержит все, что в ней произошло. источникКогда я пытался использовать
-X theirs
и другие связанные переключатели команд, я продолжал получать коммит слияния. Я, наверное, неправильно это понял. Одна из простых для понимания альтернатив - просто удалить ветку и снова отследить ее.Это не совсем «слияние», но это то, что я искал, когда наткнулся на этот вопрос. В моем случае я хотел получить изменения из удаленной ветки, которые были принудительно отправлены.
источник