Каковы команды git для перебазирования дочерней ветки, родительская ветка которой была перебазирована?

Это происходило несколько раз, когда у нас есть ветка devel, над которой над большой функцией (ветвь feature/one) работают несколько человек. Каждый разработчик ответвляется от feature/one и выполняет подзадачу. Периодически подзадачи объединяются в feature/one.

  1. Начальный граф фиксации.

    Ветви: devel отключен от main, feature/one отключен от devel и more-work отключен от функции/одного. Поскольку main не влияет на оставшуюся часть этого вопроса, он не отображается ни на каких последующих графиках коммитов.

    o--o--o (main) 
           \ 
            A---B---C (devel) 
                 \ 
                  D---E---F (feature/one) 
                       \ 
                        G---H (more-work) # one sub-task.
    

    Ветка feature/one готова к объединению, поэтому сначала ее необходимо перебазировать. Для этого команда git rebase используется следующим образом:

    git checkout devel 
    git pull 
    git checkout feature/one 
    git rebase devel 
    

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

  2. Итоговый график коммитов git:

    A---B---C (devel) 
         \   \ 
          \   D2--E2--F2 (rebased feature/one) 
           \ 
            D---E---F (original feature/one, now detached from feature/one branch) 
                 \ 
                  G---H (more-work) 
    

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

    ПРИМЕЧАНИЕ. Хэш D2 представляет собой фиксацию D, но с новым хешем, аналогично E2 и F2.

    Далее я хочу объединить more-work с feature/one.

    ВАЖНОЕ ПРИМЕЧАНИЕ: ИМО, используя вишневый выбор, будет проще достичь желаемого результата.

    Ниже приведены кратные (2 шага), необходимые для использования git rebase –onto feature/one. Это означает, что more-work необходимо сначала перебазировать на исходную feature/one (чтобы включить F коммит), а затем на rebased feature/one ветку.

  3. Сначала перебазируйте исходную функцию/функцию, чтобы включить коммит F. Я не уверен, что это можно сделать с помощью команды git, поэтому она не отображается, но результирующий график коммитов git будет выглядеть так:

    A---B---C (devel) 
        |\   \ 
        | \   D2--E2--F2 (rebased feature/one) 
        |  \ 
        |   D---E---F (original feature/one, now detached from feature/one branch) 
        |        \ 
        \         G---H (more-work) 
         \    
          D3---E3---F3 (original feature/one rehashed a 2nd time) 
                     \ 
                      G2---H2 (more-work (rebased)) 
    

    На этом этапе перебазированная ветвь more-work теперь включает в себя изменение, внесенное в хэш F, что позволяет использовать команду git rebase --onto feature/one следующим образом:

    git rebase --onto feature/one F3-hash more-work 
    
  4. После приведенной выше команды git у нас есть следующий график

    A---B---C (devel) 
        |\   \ 
        | \   D2--E2--F2 (feature/one after rebase) 
        |  \           \ 
        |   \           G3---H3 (more-work (rebased-2nd-time)) 
        |    \  
        |     D---E---F (original feature/one, now detached from feature/one branch) 
        |          \ 
        \           G---H (more-work) 
         \    
          D3---E3---F3 (original feature/one rehashed a 2nd time) 
                     \ 
                      G2---H2 (more-work (rebased)) 
    

Правильно ли я понимаю, как перебазировать дочернюю ветвь, родительская ветвь которой была перебазирована?

Ниже приведены соответствующие ссылки, которые я нашел, чтобы сформировать мое понимание того, как работает git rebase.

  • Есть ли способ перебазировать дочернюю ветку после того, как была перебазирована родительская? - этот вопрос/ответ отличается от вопроса здесь тем, что дочерняя ветвь не «обновлена» с родительской ветвью на момент перебазирования родительской ветки. И я считаю, что необходимы многочисленные перебазировки, как я иллюстрирую на своих графиках коммитов.

  • Как я могу изменить родительскую ветку? Это описано в документации git по адресу https://git-scm.com/docs/git-rebase и показывает, как ветку topic можно переместить из ветки next (она же devel в моем примере) в ветку master. .

     o---o---o---o---o  master
             \
              o---o---o---o---o  next
                               \
                                o---o---o  topic
    

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

    Команда для перебазирования на master проста.

    git rebase --onto master next topic
    

    что приводит к

        o---o---o---o---o  master
            |            \
            |             o'--o'--o'  topic
             \
              o---o---o---o---o  next
    

Другие запросы отвечали на другие вопросы

Нет никакой разницы в «изменении родительской ветки». Вы хотите изменить родительскую ветку: с версии вашей ветки до перебазирования (F3) на версию вашей ветки после перебазирования. Ветка — это не что иное, как имя коммита.

knittl 09.07.2024 17:08
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
88
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Правильно ли я понимаю, как перебазировать дочернюю ветвь, родительская ветвь которой была перебазирована?

Правильный? вроде. Идеально? нет.

Перебазирование more-work на перебазированное feature/one может и должно выполняться за один проход. Это именно тот сценарий, для которого был создан rebase --onto.

Исходная ситуация

* 9a7c139 (HEAD -> more-work) H
* 922d375 G
| * 978c327 (feature/one) F
|/
* bce6cab E
* 3cf018e D
| * 9c2aeeb (devel) C
|/
* 0c5017f B
* 8914d3a A
* fbc5771 (master) Initial commit

Перебазирование feature/one на devel

git switch feature/one && git rebase devel
* 6f50942 (HEAD -> feature/one) F
* 3cad97b E
* d0f8a97 D
* 9c2aeeb (devel) C
| * 9a7c139 (more-work) H
| * 922d375 G
| * bce6cab E
| * 3cf018e D
|/
* 0c5017f B
* 8914d3a A
* fbc5771 (master) Initial commit

Перебазирование more-work на feature/one

E_sha1=bce6cab 
git rebase --onto feature/one $E_sha1 more-work
* 6cb28df (HEAD -> more-work) H
* 1fc20f8 G
* 6f50942 (feature/one) F
* 3cad97b E
* d0f8a97 D
* 9c2aeeb (devel) C
* 0c5017f B
* 8914d3a A
* fbc5771 (master) Initial commit

Приятно использовать журнал git, чтобы показать это «в действии».

PatS 09.07.2024 19:16

В некотором роде git rebase --onto feature/one E more-work — это канонический способ сделать это, и вам не нужны два «шага», чтобы выполнить перебазирование. Перебазируйте первую ветку (git rebase deve feature/one), затем перебазируйте вторую ветку (см. первую команду перебазирования). Команда означает «принять коммиты между F и more-work и создать их копии поверх Feature/One, а затем обновить ветку more-work, чтобы она указывала на новые коммиты». git rebase --onto feature/one F more-work даст точно такой же результат, поскольку оба диапазона коммитов E..more-work и F..more-work описывают один и тот же набор коммитов (т. е. G и H).

Итак, начнем с вашей первоначальной истории:

o--o--o (main) 
       \ 
        A--B--C (devel) 
            \ 
             D--E--F (feature/one) 
                 \ 
                  G--H (more-work)

чтобы добраться до желаемой финальной истории:

o--o--o (main) 
       \ 
        A--B--C (devel) 
               \ 
                D--E--F (feature/one) 
                       \ 
                        G--H (more-work)

выполните следующие команды по порядку:

git rebase devel feature/one
git rebase --onto feature/one E more-work
# or, same result: git rebase --onto feature/one F more-work

Вы также можете попробовать простой git rebase feature/one more-work — Git обычно достаточно умен, чтобы определить, какие коммиты уже являются частью нового родителя.

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

A--B--C (devel) 
    \ 
     D--E--F (feature/one) 
            \ 
             G--H (more-work)

Чтобы оба перебазировать их в новый восходящий поток:

git rebase --update-refs devel more-work`

Это приведет к перебазированию всех коммитов между devel и more-work и обновит вашу ссылку feature/one (т. е. ветку). Итоговая история будет такой:

A--B--C (devel) 
       \ 
        D2--E2--F2 (rebased feature/one) 
                  \ 
                   G2---H2 (rebased more-work)

На самом деле все это не так уж и отличается от «изменения родительской ветки»: изначально родительская «ветвь» (ветвь — это не что иное, как имя коммита) more-work была фиксацией E (предварительная перезагрузка), и вы пытаетесь чтобы изменить его на фиксацию F2 (после перезагрузки). На самом деле не имеет значения, есть ли другие коммиты, которые являются потомками вашей ветки или вашей старой (или новой) ветки.

Но хеш для F3-hash еще не существует, когда вы запускаете git rebase --onto feature/one F3-hash more-work, если только вы не выполнили первую перезагрузку. Вы предлагаете это: git rebase --onto feature/one F more-work? Если да, то я не уверен, как GIT узнает, что я хочу перебазировать коммиты G и H.

PatS 09.07.2024 17:45

@PatS извини, ты абсолютно прав; Я скопировал хэш из неправильного ASCII-изображения из вопроса (их было слишком много :)). Я обновил свой ответ некоторыми разъяснениями, надеюсь, теперь он стал яснее. Git знает, что вы хотите перебазировать коммиты G и H, потому что вы указываете ему именно это с помощью команды: G и H — это коммиты между F и more-work (F..more-work или ^F more-work разрешается в G и H).

knittl 09.07.2024 18:10

Отличное обновление. Спасибо за пояснение. Я уже выбрал другой ответ в качестве «ответа», потому что он действительно утверждает то, что вы сейчас утверждаете. Если бы я мог выбрать два ответа, я бы это сделал. Добавление update-refs — это еще одна новинка, о которой я не знал. Еще раз спасибо!

PatS 09.07.2024 19:15

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

PatS 10.07.2024 21:12

@PatS, если перебазируемый коммит имеет тот же набор изменений, что и один из коммитов в родительских элементах, он будет пропущен.

knittl 10.07.2024 21:17

Я пытался выяснить, как git узнает, что коммит тот же, но я не уверен, откуда он это знает. Использует ли git SHA-1 содержимого изменения (то есть измененного файла), чтобы определить, что фиксация совпадает с предыдущей фиксацией? Я думал, что это произошло потому, что в хранилище объектов .git все еще были отдельные коммиты, но я запустил команду git gc, чтобы удалить все объекты, и git все равно это понял, поэтому я узнал, что git может выяснить это с другой информацией, хранящейся в коммите. .

PatS 11.07.2024 17:23

@PatS Я не смотрел реализацию, но всегда предполагал, что она будет использовать идентификатор патча . Git может вычислить идентификатор патча перед применением коммита, и если такой же патч уже существует в исходной версии, он будет проигнорирован.

knittl 11.07.2024 17:51

Другие вопросы по теме