Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Каков наилучший (и самый безопасный) способ объединить ветку Git в мастер?

Автор вопроса: moeОтветов: 12

Создана новая ветка от master, мы ее называем test.

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

Допустим, работа над test занимает несколько дней, и вы хотите постоянно обновлять test с помощью коммитов внутри master.

Я бы сделал git pull origin master из test.

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


Моя работа над test завершена, и я готов снова объединить ее с master. Вот два способа, о которых я могу думать:

А:

git checkout test
git pull origin master
git push origin test
git checkout master
git pull origin test

B:

git checkout test
git pull origin master
git checkout master
git merge test

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

Вопрос 2: Какой из этих двух методов правильный? Какая там разница?

Цель всего этого - поддерживать мою ветку test в курсе событий, происходящих в master, а позже я мог бы объединить их обратно в master, надеясь сохранить график как можно более линейным.

  • нет .. rebase никогда не перезаписывает, он просто пытается добиться более чистой истории. путем повторного прикрепления (или подделки) истории к последней точке мастера Junchen Liu 23.12.2015
  • rebase не перезаписывает ваши коммиты. Он отменяет ваши коммиты, применяет коммиты в основной ветке к вашей тестовой ветке, а затем применяет ваши коммиты к тесту. zundi 20.06.2016
  • Что, если у нас нет доступа на запись к мастеру? Есть ли способ упреждающе исправить конфликты в функциональной ветке? Наверное, нет, поскольку истории, вероятно, разошлись information_interchange 22.07.2020

gitgit-branchbranching-and-merginggit-merge

Ответы

Ответ 1 · рейтинг 3316 · KingCrunch

Как бы я это сделал

git checkout master
git pull origin master
git merge test
git push origin master

Если у меня есть локальная ветка из удаленной, мне неудобно объединять другие ветки, кроме этой, с удаленной. Кроме того, я не стал бы продвигать свои изменения, пока я не буду доволен тем, что я хочу продвинуть, а также я бы вообще не продвигал вещи, которые предназначены только для меня и моего локального репозитория. В вашем описании кажется, что test только для вас? Так что нет причин публиковать это.

git всегда старается уважать ваши и другие изменения, и --rebase тоже. Я не думаю, что могу объяснить это должным образом, поэтому взгляните на книгу Git - Rebasing или git-ready: введение в перемещение для небольшого описания. Это довольно крутая функция

Ответ 2 · рейтинг 466 · John Yin

Это очень практичный вопрос, но все приведенные выше ответы непрактичны.

Нравиться

git checkout master
git pull origin master
git merge test
git push origin master

У этого подхода есть две проблемы:

  1. Это небезопасно, потому что мы не знаем, есть ли конфликты между тестовой и главной ветвью.

  2. Он "сжал" все тестовые коммиты в один слитный коммит на главном сервере; то есть в основной ветке мы не можем видеть все журналы изменений тестовой ветки.

Итак, когда мы подозреваем, что возникнут какие-то конфликты, мы можем выполнить следующие операции git:

git checkout test
git pull
git checkout master
git pull
git merge --no-ff --no-commit test

Протестируйте merge перед commit, избегайте быстрой фиксации вперед до --no-ff,

Если возникает конфликт, мы можем запустить git status, чтобы проверить подробности конфликтов и попытаться разрешить

git status

Как только мы разрешим конфликты или если конфликта нет, мы commit и push их

git commit -m 'merge test branch'
git push

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

Итак, лучший способ - использовать rebase вместо merge (предположим, что за это время мы разрешили конфликты веток).

Ниже приведен один простой пример, для расширенных операций см. http://git-scm.com/book/en/v2/Git-Branching-Rebasing

git checkout master
git pull
git checkout test
git pull
git rebase -i master
git checkout master
git merge test

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

Единственное, чего вам нужно избегать, это: никогда не использовать rebase в общедоступной ветке, например, в главной ветке.

Никогда не выполняйте следующие операции:

git checkout master
git rebase -i test

Подробная информация о https://www.atlassian.com/git/tutorials/merging-vs-rebasing/the-golden-rule-of-rebasing.

приложение:

Ответ 3 · рейтинг 94 · raylu

Ни перебазирование, ни слияние не должны перезаписывать чьи-либо изменения (если вы не решите это сделать при разрешении конфликта).

Обычный подход при разработке:

git checkout master
git pull
git checkout test
git log master.. # if you're curious
git merge origin/test # to update your local test from the fetch in the pull earlier

Когда вы будете готовы снова слиться с мастером,

git checkout master
git log ..test # if you're curious
git merge test
git push

Если вы беспокоитесь о том, чтобы что-то сломать при слиянии, git merge --abort будет для вас.

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

Ответ 4 · рейтинг 46 · Martin Thoma

Сначала я бы сделал объединяемую ветку как можно более чистой. Запустите тесты, убедитесь, что состояние такое, какое вы хотите. Очистите новые коммиты с помощью git squash.

Помимо ответа KingCrunches, я предлагаю использовать

git checkout master
git pull origin master
git merge --squash test
git commit
git push origin master

Возможно, вы сделали много коммитов в другой ветке, а в главной ветке должна быть только одна фиксация. Чтобы сохранить историю коммитов как можно более чистой, вы можете сжать все свои коммиты из тестовой ветки в одну фиксацию в главной ветке (см. Также: Git: раздавливать или не раздавливать?). Затем вы также можете переписать сообщение фиксации на что-нибудь очень выразительное. То, что легко читать и понимать, не копаясь в коде.

изменить: вас может заинтересовать

Итак, на GitHub я делаю следующее для функциональной ветки mybranch:

Получите самую свежую информацию от источника

$ git checkout master
$ git pull origin master

Найдите базовый хеш слияния:

$ git merge-base mybranch master
c193ea5e11f5699ae1f58b5b7029d1097395196f

$ git checkout mybranch
$ git rebase -i c193ea5e11f5699ae1f58b5b7029d1097395196f

Теперь убедитесь, что только первый pick, остальные s:

pick 00f1e76 Add first draft of the Pflichtenheft
s d1c84b6 Update to two class problem
s 7486cd8 Explain steps better

Затем выберите очень хорошее сообщение о фиксации и отправьте его на GitHub. Затем сделайте запрос на перенос.

После слияния запроса на перенос вы можете удалить его локально:

$ git branch -d mybranch

и на GitHub

$ git push origin :mybranch

Ответ 5 · рейтинг 15 · Robin Wieruch

Старая ветка, но я не нашел мой путь делать это. Это может быть полезно для тех, кто работает с rebase и хочет объединить все коммиты из ветки (feature) поверх master. Если в пути возник конфликт, вы можете разрешить его для каждого коммита. Вы полностью контролируете процесс и можете прервать его в любой момент.

Обновите Master и Branch:

git checkout master
git pull --rebase origin master
git checkout <branch_name>
git pull --rebase origin <branch_name>

Объединить ветку поверх мастера:

git checkout <branch_name>
git rebase master

Необязательно: если вы столкнетесь с конфликтами во время Rebase:

Сначала разрешите конфликт в файле. Потом:

git add .
git rebase --continue

Вы можете прервать перебазирование в любое время с помощью:

git rebase --abort

Отправьте обновленную ветку:

git push origin <branch_name>

Если эта ветка была нажата раньше, вам нужно переопределить ее принудительным нажатием:

git push origin -f <branch_name>

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

Теперь у вас есть два варианта:

  • A) Создайте PR (например, на GitHub) и слейте его там через пользовательский интерфейс.
  • Б) Вернитесь в командную строку и объедините ветку с мастером
git checkout master
git merge --no-ff <branch_name>
git push origin master

Выполнено.

Ответ 6 · рейтинг 7 · djheru

Это рабочий процесс, который я использую в своей работе с командой. Сценарий такой, как вы описали. Во-первых, когда я закончил работу над test, я переустанавливаю с мастером все, что было добавлено в мастер за время, пока я работал над веткой test.

git pull -r upstream master

Это приведет к внесению изменений в мастер, поскольку вы разделили ветку test и применили их, а затем применили внесенные вами изменения для проверки "поверх" текущего состояния мастера. Здесь могут быть конфликты, если другие люди внесли изменения в те же файлы, которые вы редактировали в тесте. Если есть, вам придется исправить их вручную и зафиксировать. Как только вы это сделаете, вы сможете без проблем переключиться на главную ветку и объединить test.

Ответ 7 · рейтинг 5 · Vinay Sikarwar

git checkout master
git pull origin master
# Merge branch test into master
git merge test

Если после слияния файл был изменен, то при слиянии выйдет ошибка "Разрешить конфликт".

Итак, вам нужно сначала разрешить все свои конфликты, затем вы должны снова зафиксировать все свои изменения, а затем нажать

git push origin master

Это лучше сделать тем, кто вносил изменения в тестовую ветку, потому что он знал, какие изменения он сделал.

Ответ 8 · рейтинг 5 · user776686

Я бы использовал метод rebase. В основном потому, что он идеально отражает ваш случай семантически, т.е. вы хотите обновить состояние вашей текущей ветки и "притвориться", как если бы она была основана на последней.

Итак, даже не проверяя master, я бы:

git fetch origin
git rebase -i origin/master
# ...solve possible conflicts here

Конечно, простая выборка из источника не обновляет локальное состояние вашего master (поскольку при этом не выполняется слияние), но для нашей цели это совершенно нормально - мы хотим избежать переключения ради экономии времени.

Ответ 9 · рейтинг 4 · cgnorthcutt

Ответ @ KingCrunch должен работать во многих случаях. Одна проблема, которая может возникнуть, заключается в том, что вы можете использовать другую машину, которая должна получить последнюю версию из теста. Итак, я рекомендую сначала потянуть тест. Доработка выглядит так:

git checkout test
git pull
git checkout master
git pull origin master
git merge test
git push origin master

Ответ 10 · рейтинг 4 · omkar

Я отвечу по веткам разработки и функций,

Если вы находитесь в ветке функций и вам нужно обновить ее с помощью разработки, используйте следующие команды:

git checkout develop
git pull
git checkout feature/xyz
git merge develop

Теперь ваша feature/xyz обновлена ​​веткой develop, и вы можете отправить свои изменения на удаленный feature/xyz.

Ответ 11 · рейтинг 2 · Julian

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

От: https://git-scm.com/docs/merge-strategies

С этой опцией "рекурсивное слияние" тратит немного больше времени, чтобы избежать ошибочных слияний, которые иногда возникают из-за несущественных совпадающих строк (например, фигурных скобок из разных функций). Используйте это, когда объединяемые ветви сильно разошлись. См. Также git-diff [1] --patience.

Использование:

git fetch
git merge -s recursive -X patience origin/master

Git псевдоним

Я всегда использую для этого псевдоним, например запустить один раз:

 git config --global alias.pmerge 'merge -s recursive -X patience'

Теперь вы могли:

git fetch
git pmerge origin/master

Ответ 12 · Masoud Mokhtari

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

git checkout master
git pull

Нет необходимости проверять сначала; rebase делает правильные вещи с двумя аргументами

git rebase master test

git checkout master
git merge test

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

git push
git checkout test

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы