Работа над веткой с зависимостью от другой ветки, которая рассматривается


65

Как git помогает справиться со сценарием ниже:

У меня есть задача, разбитая на 2 части: внутренняя задача и внешняя задача. Я делаю пулл-запрос, чтобы объединить внутренние изменения и жду его слияния (и адрес обратной связи). Во время ожидания я не могу по-настоящему работать над изменениями во внешнем интерфейсе, потому что это зависит от изменений во внутреннем интерфейсе, которые еще не доступны в основной ветке.

Каков наилучший способ получить изменения в ветке изменений внешнего интерфейса из ветви внутренних изменений, пока она еще рассматривается?


14
Ну, как правило, интерфейсы внутреннего проекта должны быть четко определены. Таким образом, при запуске реализации внешнего интерфейса вас не должно беспокоить, если внутренняя логика все еще пересматривается, так как вы можете использовать макет.
Герр

17
@HerrDerb О, милый летний ребенок ...
садовник

4
Почему вы не можете написать это против вашего еще не проверенного внутреннего кода?
user253751

У вашей команды есть какая-то согласованная техника для решения этой ситуации? Если нет, возможно, вам следует договориться о чем-то подобном, поскольку это довольно распространенная ситуация.
Раду Мурзеа

Здесь ничего нет. Вот почему я задал этот вопрос. Я получил очень хорошие предложения. Я опробую предложения и посмотрю, как они работают для меня.
sul4bh

Ответы:


42

У меня тоже иногда есть эта проблема. Git очень гибкий. Вот один из способов, которым вы можете сделать это.

Ваша первая ветка featureAготова для просмотра.

Ваша вторая ветка featureBнаходится в разработке и зависит от кода в featureAветке.

Слить featureAветку в featureBветку.

Если вы вносите изменения в featureAветку, то вам следует снова объединить featureAветку с featureBветкой, чтобы включить изменения.

Вы также должны убедиться, что featureAсначала слились с основным стволом, в противном случае, когда вы слились featureBс основным стволом, вы также случайно слились featureA. После featureAслияния с основным стволом вы можете избавиться от featureAветви, поскольку featureBтеперь это зависит только от основного ствола.

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


Это имеет смысл. Позволяет ли это для отмены слияния featureAна в featureBслучае необходимости?
sul4bh

8
Операция отмены не выполняется, но, как упоминает @ 9000, вы можете создать новую ветку, и вишня выберет коммиты, из которых вы хотите сделать featureA, если вам придется начинать все сначала. Хорошо думать о ветвях Git как одноразовых. Они дешевы и просты, всегда можно сделать новую ветку. Вы можете даже создать тестовую ветку на своей featureBветке, если хотите поиграть с чем-то, в чем вы не уверены, а затем удалить его, если он не сработал, или объединить его с вашей featureBветкой, если он это сделал.
Мэтт

9
Слияние создаст беспорядок, который будет трудно (не невозможно) откатить. Я бы собрал вишневую кирку или перебазировку (то есть: вишневая крошка, все в FeatureA в основе FeatureB). Смотрите 9000 ответ.
Pierre.Sassoulas

1
Это создает сложную историю, которая будет проблемой в течение многих лет, когда кто-то захочет понять, какой код был изменен для featureA и featureB
Ian

2
если функция A обновлена, функция B должна быть перебазирована, а не объединена
Линдон Уайт

42

Держись, пропусти слияние

При таком подходе, вы не хотите , чтобы объединить ваши feature_aв feature_bнесколько раз.

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

  • Начните feature_bс feature_a, то есть:

    git checkout feature_a
    git checkout -b feature_b
    
  • Всякий раз, когда feature_aизменения ожидают слияния master, вы перебазируете feature_b их:

    ... commit something onto feature_a ...
    git checkout feature_b
    git rebase feature_a
    
  • Наконец, как только feature_aвы объединяетесь master, вы просто получаете новое masterи перезагружаете feature_aего в последний раз:

    git checkout master
    git pull origin master
    git checkout feature_b
    git rebase --onto master feature_a feature_b
    

    Эта финальная перебазировка прививает все коммиты, которые свисают с feature_aкоммита (который теперь не имеет значения, поскольку он был объединен master) прямо на master. feature_bТеперь ваша простая, стандартная ветка идет прямо от master.

РЕДАКТИРОВАТЬ: вдохновленный комментариями, немного наполовину: если вам нужно внести некоторые изменения, которые влияют на обе функции, то обязательно внесите их feature_a(а затем выполните перезагрузку, как показано на рисунке). Вы не сделать это в двух различных фиксаций в обеих ветвях, даже если может быть заманчивым; как это feature_aявляется частью истории feature_b, наличие единственного изменения в двух разных коммитах будет семантически неверным и, возможно, позже приведет к конфликтам или «воскрешению» нежелательного кода.


2
При feature_aмногократной перезагрузке вы можете столкнуться с проблемами, feature_aкоторые произошли в то же время. В результате выполнения git checkout feature_b; git rebase feature_aвы можете получить конфликты или некоторые забавные коммиты, содержащие коммиты, отменяющие новые изменения feature_a. Обычно это можно решить, используя --interactiveи пропуская коммиты, взятые из старой версии другой ветки (недавно мне приходилось делать это несколько раз).
Maaartinus

@maaartinus, спасибо за внимание, я сам не сталкивался с такими проблемами. Как rebaseи многие другие индивидуальные шаги, а не простые merge, у него, безусловно, гораздо больше шансов создать конфликты; с другой стороны, это mergeбыло бы семантически неправильно в этом случае.
AnoE

Я предполагаю, mergeчто возникли бы похожие или худшие проблемы (конфликт не так плох, как попадание в нежелательные изменения). Я рассматриваю ветвь как последовательность желаемых изменений, которым предшествует множество несвязанных изменений (логически принадлежащих другой ветке). При многократной перебазировке с одной и той же веткой я всегда удаляю несвязанные изменения, так как знаю, что они в любом случае придут (возможно, в обновленной форме), и все работает отлично.
Маартин

1
@maaartinus, я добавил небольшое дополнение по этому поводу (чтобы последовательно вносить изменения, которые должны идти в обе ветви только в базовой ветви, а не в двух разных коммитах).
AnoE

Хорошая техника. Это то, как я всегда это делаю. git rebase --ontoFTW: D
Раду Мурзеа

29

У вас уже есть ветвь, от которой зависит каждая ветка вашей функции и которая постоянно меняется. Это называется master.

Типичный способ синхронизации ветвей объектов master- это оставаться на вершине . Когда masterменяется, вы обычно git fetch origin master:master && git rebase masterв рабочем каталоге вашего филиала.

Вы можете сделать то же самое с другой веткой функций: продолжайте извлекать ее и перебрасывать поверх нее.

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


Но я думаю, что сценарий таков, что для функции b необходим код, который находится в функции a, ветвление от master не будет очень полезным. С чего мне начать? Должен ли я переходить от feature-a и поддерживать их синхронизированными, пока функция-a не будет реинтегрирована с master, а затем переназначена с master на feature-b?
Синастетический

@Sinaesthetic: вы можете, конечно , базы feature-bна feature-a, и сделать время перебазирования после времени , как feature-aменяется. Это типичный способ сделать заметным большое изменение: разбить его на part-A(основано на master), part-B(основано на part-A) и больше, если необходимо. Затем сделайте запрос на извлечение для каждой части, и рецензентам будет легче смотреть на небольшие, логически сгруппированные фрагменты.
9000

будет ли иметь значение, если я перебазирую part-b с part-a против part-b с master с точки зрения PR? Я просто хочу убедиться, что мои изменения не показывают изменения части-a как изменения части-b. Кроме того, если я сливаюсь с ребазом, как это повлияет на PR part-b? Каждый раз, когда я думаю, что понимаю эффекты, я получаю какой-то другой результат.
Lol

5

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

Ветвь функции, которая живет достаточно долго, должна сливаться с изменениями от мастера иногда (чтобы вы могли согласовать любые слияния или семантические конфликты как часть работы разработчика над веткой функций, а не как часть «обзора», qa, merge- чтобы освоить "процесс). Таким образом, вы делаете это в своей ветке переднего плана, и когда бэкэнд будет принят к мастеру, вы получите любые незначительные изменения, которые были внесены в бэкэнд как часть его проверки / принятия автоматически, по тому же маршруту, что и вы. получить любые другие изменения кода на мастере.

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

Если оказывается, что всю ветку бэкэнда нужно оставить и никогда не объединять (кажется, что это будет довольно серьезная сделка, которая случается редко), то вы либо выбираете свои коммиты для новой ветки, выходящей из мастера без бэкэнда, или вы применяете обратные коммиты, которые удаляют весь код бэкенда в ветвь веб-интерфейса. Но, как я вижу, с большей вероятностью будет приостановлена ​​работа внешнего интерфейса, пока вы не выясните, что должно заменить заменяемый сервер, а затем решите, что делать.


2

Я не вижу здесь проблемы.

У вас уже есть это каждый раз с вашей masterветкой, которая постоянно меняется, пока функции разрабатываются и затем объединяются

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

Итак, просто начните другую ветку feature_yyy_frontend. Вероятно, вы захотите перейти прямо из филиала feature_xxx_backend, чтобы эти изменения уже были в вашем филиале. затем просто разработайте внешний интерфейс, если ветвь была master.

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

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

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

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


2

Как уже упоминалось в Polygnome, вы можете фактически объединить свою ветвь внешнего интерфейса со своей внутренней веткой вместо основных. Даже с текущей настройкой ветки вы можете просто:

git checkout frontend
git merge backend

или просто

git merge backend frontend

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

Технически вы также можете делать все с rebase, но это испортит историю коммитов вашей ветки интерфейса. Откуда я родом, это считается плохой практикой. YMMV


«Weird , что никто не говорил , что вы можете объединить свою внешний интерфейс ветвь с серверной ветвью вместо мастеров:» Это было уже упомянуто, например , в моем ответе.
Полигном

Интерфейс @Polygnome не должен быть разветвлен непосредственно от бэкэнда. Они также могут быть отделены от мастера, но вы все равно можете объединить их. Таким образом, ваш ответ не упоминает об этом на самом деле.
Йорис

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

@Polygnome, тогда я неправильно понял ваш ответ. Обновлено специально для вас :-)
Joris

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

1

Большинство ответов здесь правильно описывают процесс объединения изменений из второй ветви в первую, но в них не рассматривается, как минимизировать количество конфликтов, которые вам, возможно, потребуется разрешить.

Всякий раз, когда у вас есть два набора больших изменений, которые вы хотите просмотреть по отдельности (например, featureAи featureB), создайте PR, который НЕ предназначен для слияния, но для сбора ранних отзывов о PoC of featureA.

Люди смогут быстро его просмотреть (это всего лишь PoC), и цель состоит в том, чтобы проверить общий дизайн или подход.

Затем вы можете продолжить работу с функцией A, создать для нее запрос на извлечение и выполнить ветвление и работать с функцией B.

Большая разница состоит в том, что теперь вы можете ожидать, featureAчто ничего не изменится радикально: дизайн и подход уже были проверены. Обзор кода и требуемые изменения могут быть тонкими и локальными, а не «woops, вам нужен другой подход». Это позволит свести к минимуму объем работы , что вам нужно сделать , чтобы в дальнейшем объединить featureBна featureA«ы кода, независимо от метода вы выбрали.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.