Можете ли вы «перебазировать» коммиты из удаленной ветки? - PullRequest
0 голосов
/ 03 февраля 2019

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

Есть ли способ «перебазировать» эти коммиты из ИЛИ?

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

Я думал о проверке OR / master, перебазировав его поверх моей ветки разработчика,и затем ff объединить его с моей веткой dev.

git checkout -b ORmaster OR/master
git rebase -i dev
git checkout dev
git merge --ff-only ORmaster

Но это означает, что каждый раз, когда я хочу объединиться с OR / master, я должен проверить новую ветвь и повторить это.

Есть ли более простой способ сделать это?

PS: Я также не уверен, как назвать название.Если кто-то может сказать это лучше, пожалуйста, дайте мне знать.

РЕДАКТИРОВАТЬ: я добавил, что я думаю, что я хочу, чтобы.

A--B--C                   <-- OR/master, origin/master, master

Я добавляю некоторые изменения в мою ветку

A--B--C                   <-- OR/master
       \
        D--E--F           <-- master

Кто-то еще вносит изменения в OR / master.

A--B--C--G                <-- OR/master
       \
        D--E--F           <-- master

Я хочу эти изменения, поэтому я хочу применить их к моему

A--B--C--G                <-- OR/master
       \
        D--E--F--G'       <-- master

Я хочучтобы внести другое изменение, и кто-то вносит изменения в ИЛИ

A--B--C--G--I             <-- OR/master
       \
        D--E--F--G'-H     <-- master

Я хочу применить изменение ИЛИ к моей ветви.

A--B--C--G--I             <-- OR/master
       \
        D--E--F--G'-H--I' <-- master

Насколько я понимаю, это предотвратит любое слияниефиксирует, сохраняя актуальность моего репо.

1 Ответ

0 голосов
/ 03 февраля 2019

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

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

Этот маркер может принимать любую форму, и есть встроенный, который может служить, в частности, reflog для самого OR/master.Но для иллюстрации, если ничего другого - и для большей гибкости при наличии истечения срока действия рефлога или чего-либо еще, что может вызвать проблемы - мы можем использовать явное имя ветви или тега.Имя ветки является наиболее подходящим, поскольку мы будем перемещать его обычным образом, так как Git ожидает перемещения имен ветвей.

Возьмем, к примеру, этот этап:

A--B--C--G                <-- OR/master
       \
        D--E--F--G'       <-- master

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

A--B--C--G                <-- marker, OR/master
       \
        D--E--F--G'       <-- master

Когда мы доберемся до следующего обновления,не имеет значения, сколько коммитов мы добавили в наш собственный `master, так как у нас будет:

           I              <-- OR/master
          /
A--B--C--G                <-- marker
       \
        ...

Поэтому коммиты для копирования просто marker..OR/master, и мы можем запустить:

git checkout master                 # if needed
git cherry-pick marker..OR/master   # copy the new commits

и когда это удастся, перемотайте наши marker до OR/master любым удобным для нас способом, включая довольно умный (если немного страшный):

git push . OR/master:marker

(который откажется делать что-либоесли обновление до marker не является операцией ускоренной перемотки вперед.

Но это может пойти не так

Для иллюстрации , когда идет не так, рассмотрите, что происходитесли OR/master получает серию коммитов, включающую слияние:

       ...--L
             \
           I--M--N        <-- OR/master
          /
A--B--C--G                <-- marker
       \
        ...

Теперь диапазон коммитов, marker..OR/master, включает в себя коммит M и его второго родителя L и все, что идет раньшеL это недоступно с G.Какие коммиты должны скопировать?Мы можем буквально выбрать вишню M, пока мы делаем это отдельно с аргументом -m - который всегда будет -m 1 - и это может работать длятвоя ситуация.Но это проблема, и вы должны знать об этом (и знать, что вы планируете делать с этим).Если вы используете git merge, как в моем первоначальном предложении ниже, это не проблема: все просто работает так, как должно, автоматически.

(Исходный ответ находится ниже разделительной линии.)


Все, что git rebase делает, это копирует коммиты (как будто git cherry-pick - иногда буквально * git cherry-pick), затем перемещает имя ветви.

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

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

...--F--G--H   <-- OR/master, origin/master, master

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

Теперь, в какой-то момент, вы сделали свои собственные коммиты и подтолкнули их к origin (свой собственный форк), так что теперь у вас есть:

...--F--G--H   <-- OR/master
            \
             I--J   <-- master, origin/master

Ваш origin/master всегда будет соответствовать вашему master после вас git push origin master, поэтому нам даже не нужно беспокоиться об этом здесь.

Между тем,тем не менее, люди, которые владеют репозиторием OR, делают свои собственные коммиты, так что после git fetch OR вы получаете:

...--F--G--H--K--L   <-- OR/master
            \
             I--J   <-- master

Вы можете копировать свои коммитыK и L на ваши K' и L', чтобы у вас было:

...--F--G--H--K--L   <-- OR/master
            \
             I--J   <-- master
                 \
                  K'-L'  <-- dev

, а затем вы можете быстро перемотать вперед master, чтобы у вас было:

...--F--G--H--K--L   <-- OR/master
            \
             I--J--K'-L'  <-- dev, master

В конце концов они сделают больше коммитов:

...--F--G--H--K--L--N--O   <-- OR/master
            \
             I--J--K'-L'  <-- dev, master

(я пропустил M, чтобы зарезервировать его), и, возможно, у вас также есть:

...--F--G--H--K--L--N--O   <-- OR/master
            \
             I--J--K'-L'  <-- dev
                       \
                        P--Q   <-- master

но если вы сейчас git checkout dev и git rebase OR/master, то просто скопируйте ваши I и J в I' и J' и скопируйте K', то есть копию их K, в новыйK" и так далее:

                         I'-J'-K"-L"  <-- dev
                        /
...--F--G--H--K--L--N--O   <-- OR/master
            \
             I--J--K'-L'
                       \
                        P--Q   <-- master

Это действительно никуда вас не приведет.

Если вы объедините , вы получите следующее:

...--F--G--H--K--L   <-- OR/master
            \     \
             I--J--M   <-- master

Теперь они делают свои коммиты, а вы делаете свои:

...--F--G--H--K--L----N---O   <-- OR/master
            \     \
             I--J--M--P--Q   <-- master

и еще раз вы просто git merge OR/master включаете их работу в вашу работу:

...--F--G--H--K--L----N---O   <-- OR/master
            \     \        \
             I--J--M--P--Q--R   <-- master

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

  • Вы делаете одинновый коммит, поэтому есть только одно место, где возникают конфликты.
  • После того, как вы сделали коммит слияния M, а позже R, слияние next начинается с общего слиянияbase, то есть L, а затем O: вам нужно только посмотреть на то, что они сделали с момента последнего общего коммита .

Это сам коммит слиянияэто устанавливает обновленную базу слияния с общим коммитом.Без фиксации слияния вы не получите обновленную базу слияния.Коммиты слияния хороши;обними их.: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...