Каков наилучший (и самый безопасный) способ объединить ветку 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
Если у меня есть локальная ветка из удаленной, мне неудобно объединять другие ветки, кроме этой, с удаленной. Кроме того, я не стал бы продвигать свои изменения, пока я не буду доволен тем, что я хочу продвинуть, а также я бы вообще не продвигал вещи, которые предназначены только для меня и моего локального репозитория. В вашем описании кажется, что test только для вас? Так что нет причин публиковать это.
git всегда старается уважать ваши и другие изменения, и --rebase тоже. Я не думаю, что могу объяснить это должным образом, поэтому взгляните на книгу Git - Rebasing или git-ready: введение в перемещение для небольшого описания. Это довольно крутая функция
Ответ 2 · рейтинг 466 · John Yin
Это очень практичный вопрос, но все приведенные выше ответы непрактичны.
Это небезопасно, потому что мы не знаем, есть ли конфликты между тестовой и главной ветвью.
Он "сжал" все тестовые коммиты в один слитный коммит на главном сервере; то есть в основной ветке мы не можем видеть все журналы изменений тестовой ветки.
Итак, когда мы подозреваем, что возникнут какие-то конфликты, мы можем выполнить следующие операции 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 (предположим, что за это время мы разрешили конфликты веток).
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 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.
Возможно, вы сделали много коммитов в другой ветке, а в главной ветке должна быть только одна фиксация. Чтобы сохранить историю коммитов как можно более чистой, вы можете сжать все свои коммиты из тестовой ветки в одну фиксацию в главной ветке (см. Также: Git: раздавливать или не раздавливать?). Затем вы также можете переписать сообщение фиксации на что-нибудь очень выразительное. То, что легко читать и понимать, не копаясь в коде.
Теперь убедитесь, что только первый 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. Если в пути возник конфликт, вы можете разрешить его для каждого коммита. Вы полностью контролируете процесс и можете прервать его в любой момент.
Необязательно: если вы столкнетесь с конфликтами во время Rebase:
Сначала разрешите конфликт в файле. Потом:
git add .
git rebase --continue
Вы можете прервать перебазирование в любое время с помощью:
git rebase --abort
Отправьте обновленную ветку:
git push origin <branch_name>
Если эта ветка была нажата раньше, вам нужно переопределить ее принудительным нажатием:
git push origin -f <branch_name>
Перед этим всегда проверяйте, соответствует ли ваша текущая локальная ветка вашим ожиданиям, потому что принудительная передача отменяет старую в удаленном репозитории.
Теперь у вас есть два варианта:
A) Создайте PR (например, на GitHub) и слейте его там через пользовательский интерфейс.
Б) Вернитесь в командную строку и объедините ветку с мастером
Это рабочий процесс, который я использую в своей работе с командой. Сценарий такой, как вы описали. Во-первых, когда я закончил работу над 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-diff [1] --patience.