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

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


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


Ответы (14)


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

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

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

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

person KingCrunch    schedule 09.04.2011
comment
git merge test дает мне fatal: 'test' does not point to a commit. Мне нужно найти git log точку фиксации в тестовой ветке, переключиться обратно на главную ветвь, а затем сделать git merge 0f37d3154abbf52a4cbbbb5109f08af6a7567234. - person Duncanmoo; 02.12.2014
comment
@Duncanmoo Ну, конечно, ветка test должна существовать. Конечно, вместо этого вы можете использовать хэш фиксации, но обычно проще использовать имя ветки. Внутренне он просто извлекает хэш HEAD ветки. - person KingCrunch; 04.12.2014
comment
@shanyangqu Чтобы получать последние изменения с пульта. Если вы работаете один и только с одной системой, проблем не будет. Но когда есть изменения, отправленные из другой системы (возможно, от другого разработчика), вы увидите конфликт, как только попытаетесь вернуть свое слияние (4-й шаг). Единственное решение сейчас - объединить ваш локальный мастер с мастером пультов, что в итоге приведет к довольно уродливому объединенному мастеру с объединенным коммитом origin / master. Так что всегда неплохо потянуть перед слиянием. - person KingCrunch; 25.12.2015
comment
Возможно, вы захотите провести push-тест, если резервное копирование будет выполняться только тогда, когда оно находится на вашем центральном сервере git. Это особенно хорошо, если вы работаете над собственным форком. - person Jordan Morris; 17.02.2016
comment
это показывает коммиты в fb (тестовая ветка), как если бы они были совершены прямо в мастер, в отличие от показа коммитов на их исходном fb и просто слияния с мастером (как видно с gitk или в сети gitlab) - person Joey Baruch; 11.05.2016
comment
Разве не безопаснее сначала объединить источник / мастер в тест, прежде чем объединять тест в мастер? Разве вышеупомянутый тест не устарел? - person ziggy; 17.09.2016
comment
@ziggy Ну ... Это зависит от обстоятельств. О рабочем процессе. Например, многие фиксируют только функции и исправления ошибок в develop и только исправления (и, возможно, важные исправления) в master. Затем они перенаправляют исправления из develop в master (технически вы так сказали). Однако, если исправления нет (что всегда хорошо :)), тогда develop всегда будет перед master. Так что да, вы правы, но в зависимости от рабочего процесса, возможно, в этом просто нет необходимости. (Я использовал здесь develop, потому что он более распространен, чем test). - person KingCrunch; 18.09.2016
comment
@sterling Archer лук и стрела не меняются, но цель и стратегия могут измениться :-) - person Prasad; 13.11.2016
comment
В вашем описании кажется, что тест предназначен только для вас? Так что нет причин публиковать это. Возможно, вы захотите переместить локальную ветвь на сервер, если, например, этот сервер обеспечивает резервную копию на случай отказа локального диска или если у вас нет других средств для создания резервной копии. - person Eric; 13.02.2017
comment
-1 Здесь не объясняется, в каком репозитории вы должны выполнять эти команды. Удивительно высокий балл, учитывая, насколько это бесполезно. - person Felo Vilches; 03.10.2017
comment
@FeloVilches: если вы понимаете команды, тогда вы знаете, в какой ветке вы выполняете эти команды. - person Nawaz; 03.10.2017
comment
@Nawaz действительная точка, но в заголовке указано safest way, поэтому я не уверен, насколько безопасно выполнять эти команды в случайной ветке. - person Felo Vilches; 03.10.2017
comment
@FeloVilches: Это не случайная ветка! Безопасно это или нет, это совсем другой вопрос. Но тогда вы изначально не об этом беспокоились! - person Nawaz; 03.10.2017
comment
@FeloVilches Ответ начинается с git checkout master. Предполагая, что вы читаете вывод gits, вы, вероятно, после этого будете master. Вы даже можете безопасно выполнить git checkout master в случайной ветке :) - person KingCrunch; 13.11.2017
comment
... Также я бы не стал продвигать свои изменения, пока я не буду доволен тем, что я хочу продвинуть ... почему бы не продвигать его ради резервного копирования вашего кода, если ваши локальные машины умирает и дни усилий ушли? - person Rich Steinmetz; 15.08.2018
comment
Мне этот ответ кажется неправильным. OP спрашивает, как обновлять тестовую ветку с помощью мастера - и этот ответ только показывает, как объединить тест с мастером. - person asimovwasright; 16.05.2019
comment
@KingCrunch Следует ли мне удалить ветку после слияния? - person Oliver D; 12.03.2020
comment
@OliverD Конечно, а почему бы и нет? Если ветка объединена, это означает, что коммиты теперь присутствуют более чем в 1 ветке. Удаление исходной ветки не приведет к отмене изменений. С другой стороны, воссоздание ветки находится на расстоянии одной строчки :) git checkout -b foo master - person KingCrunch; 14.03.2020
comment
Если git merge test дает fatal: refusing to merge unrelated histories, то git merge test --allow-unrelated-histories работает. - person Upulie Han; 23.10.2020
comment
Еще одна вещь ... новый git использует main, а не master - person LonelySoul; 07.02.2021

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

Нравиться

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.

приложение:

person John Yin    schedule 14.03.2015
comment
если вы не уверены в правильности операции перебазирования, обратитесь к: git-scm .com / book / en / v2 / Git-Branching-Rebasing. - person John Yin; 05.03.2016
comment
Я согласен, что можно переустановить тестовую ветку для последующего слияния с мастером. Даже другие ответы верны, это сохранит историю изменений теста ветки в главе мастера, поскольку автор упоминает, что вы получаете лайнер и гораздо более чистый проект, который является целью системы контроля версий. - person le0diaz; 05.05.2016
comment
Утверждение, что это не единственный безопасный способ, потому что мы не знаем, есть ли конфликты между тестовой ветвью и главной ветвью, неверно: всегда можно прервать слияние. И даже если нет конфликтов, вы всегда можете отменить последнюю локальную фиксацию, пока она не была нажата. Без правильного понимания git некоторые вещи могут показаться немного пугающими или непонятными, но «небезопасно» просто некорректно. Пожалуйста, будьте осторожны, чтобы не запутать других неверной информацией. - person Paul van Leeuwen; 18.08.2016
comment
согласитесь с @PaulvanLeeuwen, когда вы git merge тестовую ветку в master, вы будете уведомлены о конфликтах, и именно здесь вы вмешаетесь и объедините изменения. Как только вы закончите, вы зафиксируете слияние и вернетесь. Если вы сожалеете или не можете правильно слить его, вы всегда можете отказаться от своей работы и снова получить от мастера. Так что это точно не небезопасно .. - person Juan; 09.10.2016
comment
почему rebase -i? - person MushyPeas; 16.06.2017
comment
Ребазинг по своей сути более опасен, чем слияние. Предложение перебазирования как более безопасного варианта слияния неверно. Перебазирование - допустимая стратегия, но с большим количеством предостережений, которых следует остерегаться пользователю. - person Ikke; 31.03.2018
comment
Для тех, у кого были конфликты при перебазировании, вы можете разрешить конфликты и запустить git rebase --continue. Мне удалось успешно объединить мою ветку разработчика. Итак, теперь безопасно удалить ветку dev, если я больше не использую ее? - person Lasithds; 10.05.2019

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

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

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 в качестве средства слияния глупо. Я также не уверен, почему вы подталкиваете тест к происхождению.

person raylu    schedule 10.04.2011
comment
Этот процесс увеличит количество коммитов, каждый раз, когда вы переключаетесь между ветвями, вы должны фиксировать свою ветку. - person iBug; 21.07.2014
comment
Какие? Вы хотите сказать, что количество коммитов будет увеличиваться каждый раз, когда вы переключаете ветвь? Или вы говорите, что каждый раз, когда вы переключаете ветвь, вы должны фиксировать свою ветку? Первое неверно, и я не уверен, что означает второе. - person raylu; 21.07.2014
comment
перед оформлением заказа необходимо зафиксировать ветку. это то, что я говорю - person iBug; 22.07.2014
comment
Вы не делаете: это (одна из вещей) git stash для. - person msanford; 13.08.2014
comment
Я бы рекомендовал git checkout test; git pull вместо git merge origin/test. Еще лучше git pull --rebase. В любом случае, вы забыли вытащить изменения, поэтому перед git merge origin/test вы должны git fetch origin test (git fetch .. && git merge .. именно то, что делает git pull .. :)) - person KingCrunch; 25.12.2015
comment
Теоретически, если test находится на другом удаленном компьютере, чем master, да. Но так как у вас обычно только один пульт, вытаскивая один раз обновляет оба, а затем вы можете просто объединить (или переустановить). - person raylu; 27.12.2015
comment
Или вы можете изменить свой последний коммит (в локальной ветке) и сделать его идеальным, прежде чем нажимать. - person whihathac; 14.04.2016

Сначала я бы сделал объединяемую ветку как можно более чистой. Запустите тесты, убедитесь, что состояние такое, какое вы хотите. Очистите новые коммиты с помощью 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
person Martin Thoma    schedule 21.04.2016
comment
который должен быть только одним коммитом в главной ветке, ну не обязательно; Вы можете захотеть сохранить историю - person Cocowalla; 12.04.2018
comment
Конечно. Но тогда просто не подавляйте коммиты - person Martin Thoma; 12.04.2018
comment
Я думаю, что --first-parent кажется лучшим решением. davidchudzicki.com/posts/first-parent - person bkribbs; 21.09.2018

Старая ветка, но я не нашел мой путь делать это. Это может быть полезно для тех, кто работает с 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

Выполнено.

person Robin Wieruch    schedule 31.10.2018
comment
Мне это тоже нравится. Одна вещь, которую вы забыли упомянуть, это то, что вам часто приходится принудительно нажимать ваше ‹branch_name› после того, как вы перебазируете. - person kenecaswell; 30.03.2021

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

git pull -r upstream master

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

person djheru    schedule 16.03.2016

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

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

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

git push origin master

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

person Vinay Sikarwar    schedule 07.04.2015

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

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

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

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

person user776686    schedule 13.09.2018

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

git checkout test
git pull
git checkout master
git pull origin master
git merge test
git push origin master
person cgnorthcutt    schedule 28.02.2020

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

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

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

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

person omkar    schedule 20.05.2020

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

От: 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
person Julian    schedule 16.11.2019

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

git checkout master
git pull

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

git rebase master test  

git checkout master
git merge test

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

git push
git checkout test
person Masoud Mokhtari    schedule 15.11.2019

Это из GitLab: просто следуйте инструкциям:

введите здесь описание изображения

person shdr    schedule 05.12.2019
comment
В step-1 вы проверяете некоторую функциональную ветку, а затем в step-2 вы снова проверяете основную ветку. Я запутался, зачем вообще проверять ветку функций ?? Пожалуйста, объясни - person Muhammad Tariq; 17.01.2021
comment
Это потому, что в этом сценарии сначала выполняется выборка из исходной (удаленной) ветки функции. после этого, чтобы объединить функцию в мастер, вам нужно оформить заказ и объединить с ней функцию. - person shdr; 18.01.2021
comment
Тогда в первом случае git fetch origin feature не должно быть второй командой после проверки ветки удаленной функции для синхронизации локальной с удаленной функцией? - person Muhammad Tariq; 18.01.2021

Я всегда получаю конфликты слияния, когда делаю просто git merge feature-branch. Мне кажется, это работает:

git checkout -b feature-branch

Сделайте кучу изменений кода ...

git merge -s ours master 
git checkout master
git merge feature-branch

or

git checkout -b feature-branch

Сделайте кучу изменений кода ...

git checkout master
git merge -X theirs feature-branch
person mchavezi    schedule 27.09.2020