Почему я объединяю «исходную / развивающуюся ветку удаленного отслеживания» с разработкой?

125

Я единственный в своей организации, кто совершает коммиты со следующим сообщением:

Объединить ветку удаленного отслеживания origin / develop с develop

Не уверен, что делаю, чтобы вызвать их, но я бы хотел остановиться.

Какую команду я использую для создания этой фиксации и какую команду я должен использовать, чтобы ее не создавать?

Джордан Фельдштейн
источник
1
Ответ Ричарда Хансена прекрасен. Но я думаю, это может сбить с толку новичков. Мое решение - продолжать выполнять pull --rebase, но, чтобы избежать опасности, я прячу свои изменения перед вытягиванием. Потом, натянув, наношу. Я разрешаю конфликты. Наконец-то я могу зафиксировать и нажать.
Johnjohn
У git pull --autostash --rebaseвас работает @Johnjohn?
sourcedelica

Ответы:

206

git pullвероятно создает фиксацию. Если вы делаете локальную фиксацию, а затем запускаете git pullпосле того, как кто-то другой отправляет фиксацию в репозиторий, Git загружает фиксацию другого разработчика, а затем объединяет ее в вашу локальную ветвь.

Как избежать этих коммитов слияния в будущем

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

Вместо этого я рекомендую вам следовать этой схеме использования:

# download the latest commits
git remote update -p

# update the local branch
git merge --ff-only @{u}

# if the above fails with a complaint that the local branch has
# diverged:
git rebase -p @{u}

объяснение

  • git remote update -pзагружает все коммиты в удаленные репозитории и обновляет ветки удаленного отслеживания (например, origin/master). Он НЕ касается вашего рабочего каталога, индекса или локальных ветвей.

    В -pаргументе чернослив удаляется вверх по течению ветви. Таким образом, если fooветка будет удалена в originрепозитории, git remote update -pавтоматически будет удалена ваша origin/fooссылка.

  • git merge --ff-only @{u}указывает Git объединить ветвь восходящего потока ( @{u}аргумент) с вашей локальной ветвью, но только если ваша локальная ветвь может быть «быстро перенаправлена» в восходящую ветвь (другими словами, если она не разошлась).

  • git rebase -p @{u}эффективно перемещает коммиты, которые вы сделали, но еще не отправили поверх ветки восходящего потока, что избавляет от необходимости создавать глупые коммиты слияния, которых вы пытаетесь избежать. Это улучшает линейность истории разработки, облегчая просмотр.

    Эта -pопция указывает Git сохранять слияния. Это предотвращает линеаризацию Git перемещаемых коммитов. Это важно, если, например, вы объединили ветку функции в master. В противном случае -pкаждая фиксация в функциональной ветке будет дублироваться masterкак часть линеаризации, выполняемой git rebase. Это затруднит, а не облегчит просмотр истории разработки.

    Остерегайтесь : git rebaseможет не получиться то, что вы ожидаете, поэтому просмотрите результаты, прежде чем нажимать. Например:

    git log --graph --oneline --decorate --date-order --color --boundary @{u}..
    

Я предпочитаю этот подход по git pull --rebaseследующим причинам:

  • Это позволяет вам видеть входящие коммиты восходящего потока, прежде чем вы измените свою историю, чтобы включить их.
  • Он позволяет вам передать опцию -p( --preserve-merges) git rebaseв случае, если вам нужно переустановить намеренное слияние (например, слияние уже размещенной ветки функции master).

Сокращение: git upвместоgit pull

Чтобы упростить выполнение описанного выше, я рекомендую создать псевдоним с именем up:

git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'

Теперь все, что вам нужно сделать, чтобы обновить ветку, - это запустить:

git up

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

А почему бы и нет git pull --rebase?

Бег git pull --rebaseэквивалентен бегу с git fetchпоследующим git rebase. Это пытается перемотать вперед к новым коммитам восходящего потока, но если это невозможно, он перебазирует ваши локальные коммиты на новые коммиты восходящего потока. Обычно это нормально, но будьте осторожны:

  • Перебазирование - это сложная тема, и вы должны понимать последствия, прежде чем выполнять ребазирование.
  • git pull --rebaseне дает вам возможности изучить коммиты перед их включением. В зависимости от того, что изменилось вверх по течению, то вполне возможно , что перебазироваться неправильная операция-а rebase --onto, merge, resetили push -fможет быть более подходящим , чем равнины rebase.
  • Невозможно (в настоящее время) перейти --preserve-mergesк операции rebase, поэтому любое намеренное слияние ветки функции будет линеаризовано, воспроизводя (и, таким образом, дублируя) все коммиты ветки функции.

«Исправление» существующей фиксации слияния, созданной git pull

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

git rebase @{u}

Вышеупомянутая команда указывает Git выбрать все коммиты без слияния, доступные из HEAD(текущий коммит), за вычетом всех коммитов, доступных из @{u}(что является сокращением для «восходящей ветки», то есть, origin/masterесли HEADесть master), воспроизведение (вишневый выбор ) их поверх восходящей ветки, а затем переместите ссылку на текущую ветвь так, чтобы она указывала на результат воспроизведения коммитов. Это эффективно перемещает коммиты без слияния на самую последнюю фиксацию восходящего потока, что устраняет слияние, созданное с помощью git pull.

Если у вас есть намеренная фиксация слияния, вы не хотите запускать, git rebase @{u}потому что она будет воспроизводить все из другой ветки. Разобраться с этим случаем значительно сложнее, поэтому его хорошо использовать git upи git pullвообще избегать . Вероятно, вам придется использовать resetдля отмены слияния, созданного, pullа затем сделать git rebase -p @{u}. -pАргумент git rebaseнадежно не работает для меня, так что вы могли бы в конечном итоге, чтобы использовать , resetчтобы отменить преднамеренное слияние, обновить локальную ветвь @{u}, а затем повторить намеренное слияние (который является болью , если там было много волосатого слияние конфликты).

Ричард Хансен
источник
+1 за обсуждение --preserve-merges, за исключением того, что вы фактически не задокументировали это в командах, которые вы сказали ему запустить, поэтому -1 для этого.
Сет Робертсон,
@Seth: Спасибо за комментарий; Я обновил ответ, чтобы рекомендовать -p. Я избегал рекомендовать его раньше, потому что он не нужен очень часто и его поведение плохо документировано.
Ричард Хансен
3
В чем разница между git remote update -pи git fetch?
eckes
3
@eckes: git remote update -pто же самое, что и git fetch --all -p. Я привык использовать git remote update -pобратно, когда fetchне было -pвозможности.
Ричард Хансен,
1
@ user1914692: После завершения слияния Git обновит локальную ветвь, чтобы указать на вновь созданную фиксацию слияния, а не на ту же фиксацию, что и удаленная ветвь. Эта новая фиксация слияния представляет собой проблему, особенно при нажатии.
Ричард Хансен
18
git fetch
git rebase origin/master

Это должно сработать. Или, если вы хотите продолжать использовать pull

git pull --rebase

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

git pull

Подробнее об этом в разделе «Вытягивание с перебазированием вместо слияния» на этой странице:

http://mislav.uniqpath.com/2010/07/git-tips/

Адам Димитрук
источник