Git pull приводит к появлению посторонних сообщений «Merge branch» в журнале фиксации

110

Я работаю с другим разработчиком над проектом, и мы используем Github в качестве удаленного репозитория. Я на Mac использую git 1.7.7.3, он в Windows использует git 1.7.6.

Вот что происходит

  1. Один из нас (назовем его разработчиком A, но неважно, какой) отправляет набор коммитов на GitHub.
  2. Другой (разработчик B) делает некоторые локальные коммиты.
  3. B делает а git pull.
  4. B делает а git push.
  5. Глядя на журнал истории коммитов, я вижу «master» ветки слияния на github.com:foo/bar

Журнал фиксации со временем засоряется сообщениями «Объединить ветвь», а также показывает, что разработчик Б фиксирует изменения, сделанные разработчиком А. Единственный способ, который мы нашли для предотвращения этой проблемы, - это выполнить git pull --rebaseна шаге 3, но я не знаю, какие побочные эффекты представит перебазирование. Я впервые работаю над репозиторием git для нескольких разработчиков, так что это нормальное поведение? Есть мысли, как решить эту проблему?

мшафрир
источник
2
Вы можете просмотреть журнал без слияния сgit log --no-merges
wjandrea

Ответы:

88

Фиксация, которую вы видите, прекрасна. A pullэффективно запускается, git fetchа затем, git mergeкогда вы запускаете, обычно происходит слияние git pull.

Альтернатива использованию перебазирования вместо слияния возможна, но обычно этого следует избегать. Ребазинг позволяет сохранить линейную историю, но также удаляет любую информацию о ветвлении, которое произошло изначально. Это также приведет к перезаписи истории текущей ветки, воссозданию всех коммитов, которые не содержатся в целевой ветке (в вашем случае, удаленной). Поскольку воссозданные коммиты представляют собой разные коммиты, это может вызвать большую путаницу при совместной разработке, особенно когда люди уже проверили части этих коммитов до того, как они будут переписаны (например, с ветвями функций). Итак, как правило, вы никогда не должны переписывать какой-либо коммит, который уже был отправлен.

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

Итак, короче: да, коммиты слияния - это прекрасно, и вам не стоит о них беспокоиться.

совать
источник
2
Очень хороший ответ. Я сам пробовал использовать стиль rebase, поскольку он рекомендовался в некоторых руководствах по участию в проектах с открытым исходным кодом, и это вызвало у меня проблемы. То же было и у нового члена команды. Я думаю, что вариант перебазирования не предназначен для команд, работающих вместе весь день, но подходит для проектов, в которых есть основные участники и другие участники, которые просто отправляют исправления. Они должны быть в порядке, получая основное репо и изменяя свои изменения непосредственно перед отправкой запроса на перенос.
Meligy
2
@sTodorov Если новых изменений нет, то извлекающая часть извлечения ничего не сделает, но слияние все еще выполняется. Поэтому, если ваша текущая локальная ветка устарела, новые изменения будут добавлены в вашу ветку. И если он не может выполнить слияние с перемоткой вперед (если у вас расходящиеся коммиты), он создаст коммит слияния.
poke
28
Этот ответ создает впечатление, что использование rebase, как описано в OP, опасно, но это не так. Перебазирование на шаге 3 не перезаписывает всю историю. Только локальные коммиты, которые не были отправлены, перезаписываются путем повторного применения поверх нового HEAD (последнего коммита, отправленного в эту ветку). Это предотвращает посторонние коммиты слияния и не имеет других побочных эффектов.
Боб Эспонья 08
1
@bobesponja Переписываются все коммиты, которых нет в удаленной удаленной ветке. Это может включать опубликованные коммиты из других веток, например, с ветвями функций, к которым другие, возможно, уже обращались раньше. Таким образом, да, перебазирование, не думая о том, что вы переустанавливаете, несколько опасно.
тык
1
@bobesponja. Да, если вы публикуете свою функциональную ветку раньше (потому что другие работают над ней или просто в качестве резервной копии), вам не следует переустанавливать ее, потому что другие уже могли ее получить. В таком случае, как вы сами говорите, ребейзинг идет вразрез с рекомендациями, которые я сформулировал в своем ответе. Однако, если вы не публикуете свои коммиты, то перебазирование подойдет, если вы хотите и не возражаете против линейной истории. Но это зависит от того, как вы работаете, поэтому общий ответ - избегать этого, если это действительно не безопасно. Btw. Я изменил свой ответ, поэтому, если проблема будет решена, буду признателен, если вы удалите свой голос против.
тык
48

Этот ответ был изменен, поскольку мое понимание, диаграммы и выводы были неверными.


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

Например, два человека работают в одной ветке. Ветвь начинается как:

...->C1

Первый человек заканчивает свою работу и толкает в ветку:

...->C1->C2

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

...->C1->C3

Если вытягивание настроено на слияние, репозиторий второго лица будет выглядеть так.

...->C1->C3->M1
      \      /
       ->C2->

Где M1 - это фиксация слияния. История этой новой ветки будет отправлена ​​в репо. Если бы вместо этого был установлен pull для перебазирования локального репо, это выглядело бы так:

...->C1->C2->C3

Нет фиксации слияния. История сделана более линейной.

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

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

Вы можете установить branch.autosetuprebase = always, чтобы git автоматически устанавливал ваши удаленные ветки как rebase вместо master.

git config --global branch.autosetuprebase always

Этот параметр заставляет git автоматически создавать параметр конфигурации для каждой удаленной ветки:

branch.<branchname>.rebase=true

Вы можете установить это самостоятельно для своих удаленных веток, которые уже настроены.

git config branch.<branchname>.rebase true

Я хотел бы поблагодарить @LaurensHolst за вопросы и продолжение моих предыдущих утверждений. Я определенно узнал больше о том, как git работает с коммитами pull и merge.

Для получения дополнительной информации о коммитах слияния вы можете прочитать участие в проекте в ProGit-Book . Раздел Private Small Team показывает коммиты слияния.

Билл Дверь
источник
7
«Использование перебазирования вместо слияния при извлечении обеспечивает правильную историю для общего репозитория. Использование слияния дает ложную историю ». - Чем обосновано это довольно смелое заявление? История со слияниями не может быть «ложной историей». Это точное изображение порядка, в котором происходили события. То, что вы делаете путем перебазирования, на самом деле изменяет историю, чтобы создать ее немного более линейную версию. Вы жертвуете точностью ради эстетики. Может быть, что-то вы предпочитаете делать, но отнюдь не правдивее.
Laurens Holst
2
Использование rebase вместо слияния не жертвует точностью ради эстетики. Мы используем --no-ff для слияния, поэтому эстетика не является требованием. Точность - это желание. Rebase обеспечивает такую ​​точность.
Bill Door
2
Как точнее перебазированная история? Вы этого не поясняете, и я не понимаю, как бы это было.
Laurens Holst
1
История - это отражение времени, когда в общем репо произошли фиксации . Однажды в первый день в общем репо произошла фиксация C2. На второй день в общем репо фиксируется фиксация C3. Если бы C3 был раньше C2, то время было бы неверным. C3 не предшествовал C2. Все, что делает это перебазирование, - это реорганизация коммитов в локальном репозитории, чтобы должным образом отразить историю, показанную в общем репозитории.
Билл Дор
6
Ваши вопросы заставили меня пересмотреть мое понимание коммитов слиянием. Моя диаграмма неверна. Пересматриваю обсуждение. Мои выводы тоже неверны. История перебазирования и слияния одинаково верна. Вы можете сделать свой выбор.
Билл Дор
11

Ты можешь сделать:

git pull --rebase

Однако в этом случае ваши изменения всегда будут важнее ваших соавторов. Но вы не получите никаких загрязняющих сообщений о слиянии.

gaborous
источник
9

На самом деле есть гораздо более простой ответ. Просто пусть разработчик Б потянет ДО того, как сделать коммит. Это предотвратит эти коммиты слияния, поскольку они вызваны историей, которую вы создали в своем локальном репо, из вашей локальной фиксации, пытающейся слиться с историей коммитов в удаленном репо. Если при вытягивании вы получаете сообщение вроде «изменения будут перезаписаны», это просто означает, что вы оба коснулись одного и того же файла, поэтому сделайте следующее:

git stash
git pull
git stash pop

тогда вы можете разрешить любые конфликты слияния, если они есть.

Люк
источник
Наиболее раздражающими и тревожными являются именно конфликты слияния. Я предпочитаю этого избегать
Грин
1
@Green Если вас беспокоят конфликты слияния, то даже git pull ничем не отличается.
Zoso
За исключением того случая, когда ты забываешь об этом stashраньше pull. Ух, мерзавец требует, чтобы я все время был на вершине своей игры.
linuxNoob
Нужно git pull --rebase любом случае интегрировать удаленные изменения раньше, чем локальные.
vonbrand
7

Выполнение git pull вставит сообщения «Объединить ветку», это именно то, что он делает. Выполнив git pull, вы объединили удаленную ветку с локальной веткой.

Когда вы выполняете git pull и возникают конфликты, в журнале git будут отображаться обновления конфликтующих файлов, поступающие от пользователя, который разрешил конфликты. Я предполагаю, что это связано с тем, что человек, который исправляет конфликт, повторно фиксирует файл.

Насколько я знаю, именно так работает git, и другого пути нет.

Ребазинг уничтожит историю git, поэтому вы не сможете увидеть, когда произошло слияние.

Kclair
источник