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

git pull origin demo
git checkout master
git pull origin master
git merge demo
git push origin master

Меня беспокоит только , если есть какие-либо проблемы слияния, я хочу сказать git перезаписать изменения в ветке master, не давая мне запроса на слияние. Таким образом, изменения в ветке demo должны автоматически перезаписывать изменения в ветке master.

Я осмотрелся, есть несколько вариантов, но я не хочу рисковать слиянием.

OpenStack

Ответов: 7

Ответы (7)

На самом деле не имеет отношения к этому ответу, но я бы отказался от git pull, который просто запускает git fetch, за которым следует git merge. Вы выполняете три слияния, что заставит ваш Git выполнить три операции выборки, когда вам достаточно одной выборки. Отсюда:

git fetch origin   # update all our origin/* remote-tracking branches

git checkout demo         # if needed -- your example assumes you're on it
git merge origin/demo     # if needed -- see below

git checkout master
git merge origin/master

git merge -X theirs demo   # but see below

git push origin master     # again, see below

Контроль самого сложного слияния

Самая интересная часть здесь git merge -X theirs. Как указано в root545, параметры -X передаются в стратегию слияния, и как стратегия по умолчанию рекурсивная, так и альтернативная разрешитьстратегия возьмите -X наши или -X их (один или другой, но не оба). Однако, чтобы понять, что они делают, вам нужно знать, как Git находит и обрабатывает конфликты слияния.

Конфликт слияния может возникнуть в каком-либо файле1, когда версия base отличается от версии current (также называемой local, HEAD или --ours) версия и другая (также называемая удаленной или - их) версия того же файла. То есть слияние выявило три ревизии (три коммита): базовую, нашу и их. «Базовая» версия взята из базы слияния между нашей фиксацией и их фиксацией, как показано на графике фиксации (для более подробной информации см. Другие сообщения StackOverflow). Затем Git обнаружил два набора изменений: «что мы сделали» и «что они сделали». Эти изменения (как правило) обнаруживаются построчно, чисто текстовым. Git не имеет реального понимания содержимого файлов; это просто сравнение каждой строки текста.

Эти изменения вы видите в выводе git diff, и, как всегда, они имеют context. Возможно, что то, что мы изменили, находится в разных строках от того, что они изменили, так что кажется, что изменения не будут противоречить друг другу, но контекст также изменился (например, из-за того, что наше изменение было близко к верху или низу файла, так что в нашей версии файл закончился, но в их они также добавили больше текста вверху или внизу).

Если изменения происходят в разных строках - например, мы меняем цвет на цвет в строке 17, и они меняют fredна barney в строке 71 - тогда конфликта нет: Git просто принимает оба изменения. Если изменения происходят в тех же строках, но являются идентичными изменениями, Git берет одну копию изменения. Конфликт изменения / изменения может возникнуть только в том случае, если изменения находятся в тех же строках, но являются разными изменениями или в этом особом случае мешающего контекста.

Параметры -X ours и -X theirs сообщают Git, как разрешить этот конфликт, выбирая только одно из двух изменений: наше или их. Поскольку вы сказали, что объединяете demo (их) в master (наши) и хотите изменений из demo, вам нужно -X их.

Слепое применение -X, однако, опасно. Тот факт, что наши изменения не противоречили построчно, не означает, что наши изменения фактически не конфликтуют! Один классический пример встречается в языках с объявлениями переменных. В базовой версии может быть объявлена ​​неиспользуемая переменная:

int i;

В нашей версии мы удаляем неиспользуемую переменную, чтобы предупреждение компилятора исчезло, а в их версии они добавляют цикл несколькими строками позже, используя i в качестве цикла. прилавок. Если мы объединим два изменения, полученный код больше не будет компилироваться. Параметр -X здесь не поможет, так как изменения внесены в разные строки.

Если у вас есть автоматизированный набор тестов, самое важное, что нужно сделать, - это запустить тесты после слияния. Вы можете сделать это после фиксации и при необходимости исправить позже; или вы можете сделать это перед фиксацией, добавив - no-commit к команде git merge. Подробности обо всем этом оставим в других публикациях.


1Вы также можете получить конфликты в отношении "файловых" операций, например, возможно, мы исправим написание слова в файле (чтобы у нас было изменение), и они удалить весь файл (чтобы было удаление). Git не разрешит эти конфликты самостоятельно, независимо от аргументов -X.


Выполнение меньшего количества слияний и / или более интеллектуальных слияний и / или использование перебазирования

В обеих последовательностях команд есть три слияния. Первый - перенести origin / demo в локальный demo (ваш использует git pull, который, если ваш Git очень старый, не сможет обновить origin / demo, но даст тот же конечный результат). Второй - перенести origin / master в master.

Мне непонятно, кто обновляет demo и / или master. Если вы пишете свой собственный код самостоятельно demo branch, и другие пишут код и отправляют его в demo ветку на origin, то это слияние на первом этапе может иметь конфликты или привести к настоящему слиянию. Чаще всего для объединения работы лучше использовать rebase, чем merge (правда, это вопрос вкуса и мнения). Если это так, вы можете вместо этого использовать git rebase. С другой стороны, если вы никогда не выполняете свои собственные коммиты на demo, вам даже не нужна ветка demo. В качестве альтернативы, если вы хотите автоматизировать большую часть этого, но иметь возможность тщательно проверять, есть ли коммиты, сделанные вами и другими, вы можете использовать git merge --ff-only origin / demo: это перемотает вашу демонстрационную версию, чтобы она соответствовала обновленной origin / demo, если это возможно, и просто полностью потерпит неудачу, если нет (в этот момент вы можете проверить два набора изменений, и выберите соответствующее слияние или перебазирование).

Та же самая логика применима к master, хотя вы выполняете слияние на master, поэтому вам определенно понадобится master. Тем не менее, даже более вероятно, что вы захотите, чтобы слияние завершилось неудачно, если оно не может быть выполнено в виде быстрой перемотки вперед без слияния, поэтому это, вероятно, также должно быть git merge --ff-only origin / master.

Допустим, вы никогда не делаете свои собственные коммиты на демо. В этом случае мы можем полностью отказаться от названия demo:

git fetch origin   # update origin/*

git checkout master
git merge --ff-only origin/master || die "cannot fast-forward our master"

git merge -X theirs origin/demo || die "complex merge conflict"

git push origin master

Если вы делаете свои собственные демо фиксации ветки, это бесполезно; вы также можете сохранить существующее слияние (но, возможно, добавить - ff-only в зависимости от того, какое поведение вы хотите), или переключить его на выполнение перебазирования. Обратите внимание, что все три метода могут дать сбой: слияние может завершиться ошибкой с конфликтом, слияние с - ff-only может не иметь возможности быстрой перемотки вперед, а перебазирование может завершиться сбоем с конфликтом (перебазирование работает, в сущность, выбор вишни коммит, который использует механизм слияния и, следовательно, может вызвать конфликт слияния).

Эти команды помогут перезаписать код ветки demo в master

git fetch --all

Вытащите вашу демонстрационную ветку на локальную

git pull origin demo

Теперь оформить заказ на master ветку. Эта ветка будет полностью изменена кодом на демо ветка

git checkout master

Оставайтесь в ветке master и выполните эту команду.

git reset --hard origin/demo

reset означает, что вы будете сбрасывать текущую ветку

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

origin / demo будет ветвью, которая будет считаться кодом, принудительно перезаписывающим текущую master ветку

Результат выполнения вышеуказанной команды покажет вам ваше последнее сообщение о фиксации на ветке origin / demo или demo enter image description here

Затем, в конце, принудительно вставьте код из ветки master в ваше удаленное репо.

git push --force

Этот подход слияния добавит одну фиксацию поверх master, которая вставит все, что есть в feature, без жалоб на конфликты или другую чушь.

enter image description here

Прежде чем что-либо трогать

git stash
git status # если здесь что-то появится, переместите его на рабочий стол

Теперь подготовим мастер

мастер проверки git
git pull # если на этом этапе есть проблема, она выходит за рамки этого ответа

Получить особенность одеты

функция проверки git
git merge --strategy = наш мастер

Убейте

мастер проверки git
git merge --no-ff функция

У меня была такая же проблема, и я нашел решение здесь. Не забудьте прочитать документацию, прежде чем что-либо делать.

Позвольте мне объяснить. Учтите, что у нас есть 2 репозитория master и devmaster, и вы хотите заменить master на devmaster. Тогда первая команда будет такой, как показано ниже

git checkout devmaster

Теперь вы перешли на ветку devmaster. И нужно слить с нашим (ссылка):

git merge -s ours master

Тогда проверьте код:

git checkout master

Следующий этап - слияние devmaster с master:

git merge devmaster

Заключительный этап - введите свой код:

git push

Но, пожалуйста, прочтите всю документацию, потому что это сработало. Это не Гарантировано, что это сработает и для вас.

Вы можете попробовать «наш» вариант в git merge,

git merge branch -X наш

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

Когда я пытался использовать -X их и другие связанные переключатели команд, я продолжал получать коммит слияния. Я, наверное, неправильно это понял. Одна из простых для понимания альтернатив - просто удалить ветку и снова отследить ее.

git branch -D 
git branch --track  origin/

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

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

Решение, которое я нашел, заключалось в использовании git merge -s ours branch.

Обратите внимание, что это вариант -s, а не -X.-s обозначает использование нашего в качестве стратегии слияния верхнего уровня, -X будет применять параметр наш к рекурсивная стратегия слияния, чего я (или мы) не хочу в данном случае.

Шаги, где oldbranch - это ветвь, которую вы хотите перезаписать newbranch.

  • git checkout newbranch проверяет ветку, которую вы хотите сохранить
  • git merge -s ours oldbranch объединяет старую ветку, но сохраняет все наши файлы.
  • git checkout oldbranch проверяет ветку, которую вы хотите перезаписать
  • get merge newbranch объединяет в новую ветку, перезаписывая старую ветку

2022 WebDevInsider