Слияние из восходящей удаленной ветви в локальную удаленную ветку - PullRequest
0 голосов
/ 12 сентября 2018

Мы используем модель ветвления в нашей организации, и я пытаюсь объединить обновления из вышестоящей ветки с моей локальной ветвью.

Это моя настройка git.

kartik@ ~/sourcecode/myproject (defect-875) $ git remote -v
origin  git@github.com/kartik/myproject.git (fetch)
origin  git@github.com/kartik/myproject.git (push)
upstream    git@github.com:MyOrg/myproject.git (fetch)
upstream    git@github.com:MyOrg/myproject.git (push)

В восходящем потоке есть две ветви

  1. master

  2. devel

Мне нужно синхронизировать мой локальныйветвь с devel ветвью вверх по течению.

Это то, что я пробовал

git fetch upstream
git merge upstream/defect-875

, где дефект-875 - моя локальная ветвь.

Я всегда получаю это сообщение об ошибке

объединение: upstream / дефект-875 - не то, что мы можем объединить

Я также пробовал это

kartik@ ~/sourcecode/myproject (defect-875) $ git merge upstream/devel -m "Merging from seo redirect."
 merge: upstream/devel - not something we can merge

Как мне решить эту проблему

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

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

Первое, что нужно знать о Git, это то, что в основном это совершает .Ветви - или, на самом деле, ветви names (см. Что именно мы подразумеваем под "веткой"? ) - существуют в Git, так что Git и мы можем найти коммиты.

Вы, вероятно, уже знаете, что коммит, по сути, является снимком дерева исходных текстов.(Если вы этого не сделали, ну, теперь вы делаете!) Но у этого есть и немного больше.Во-первых, каждый коммит имеет уникальное «истинное имя» в форме своего хеш-идентификатора.Имя ветви - это способ выразить истинное имя некоторого коммита - идентификатор хеша - и git rev-parse покажет вам фактический идентификатор хеша:

$ git rev-parse master
c05048d43925ab8edcb36663752c2b4541911231

Эти большие уродливые идентификаторы кажутся случайными, но на самом делеполностью определяется содержанием самого коммита.Это содержимое довольно короткое - вот вышеупомянутый коммит, с немного помешанным @<address> для сокращения спама:

$ git cat-file -p c05048d43925ab8edcb36663752c2b4541911231 | sed 's/@/ /'
tree a446a29ef7ca90d9c64825fb00a0f1e1a099ca18
parent e9983f8965c0875cc6727e9644c84ff1dfc99372
author Junio C Hamano <gitster pobox.com> 1536096807 -0700
committer Junio C Hamano <gitster pobox.com> 1536096807 -0700

Git 2.19-rc2

Signed-off-by: Junio C Hamano <gitster pobox.com>

Строка tree выше - это то, как коммит сохраняет исходный кодснимок (с помощью другого внутреннего объекта Git).Строки author и committer говорят нам, кто сделал коммит и когда - 1536096807 означает Tue Sep 4 14:33:27 2018.Строка parent дает большой некрасивый хеш-идентификатор коммита, который приходит до этого коммита.

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

...  <-c05048d43925ab8edcb36663752c2b4541911231   <--master

имя master указывает на этот коммит, который указывает на более ранний коммит e9983f8965c0875cc6727e9644c84ff1dfc99372.Эта более ранняя фиксация указывает на более раннюю фиксацию и т. Д.

Все эти имена и объекты являются локальными для вашего собственного репозитория

У вас есть все эти имена веток, например, master и defect-875, в вашем собственном хранилище.Они не зависят ни от чего, кроме вашего собственного Git.Они также указывают на ваши коммиты, которые есть у вас локально, и эти коммиты, включая их снимки и родительские коммиты, а также снимки этих коммитов на протяжении всей истории, также не зависят ни от чего, кроме вашего Git.

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

git fetch получает их коммиты, которых у вас нет

Их имена ветвей не обязанысовпадают, но идентификаторы хеша фиксации do должны совпадать.Либо они совпадают, и у вас есть коммит, либо у них есть коммит, которого нет у вас.Итак, ваш Git вызывает свой Git и говорит: Какие у вас имена и каковы их хэш-идентификаторы коммитов? Их Git дает вашему Git этот список, а ваш Git говорит себе: ах, яесть этот или хм, у меня его нет. Ваш Git затем дает своему Git список коммитов, которые они имеют, которые ваш Git хочет , и ихGit упаковывает эти коммиты, включая их снимки, и отправляет их.

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

git fetch также получает имена веток;что теперь?

У тебя тоже есть свои бримена якоря.Но это их названий веток, так что теперь ваш Git переименовывает эти вещи.Если ваш Git вызвал свой Git с помощью git fetch upstream, ваш Git переименовал в master, назвав его upstream/master, и переименовал в devel, назвав его upstream/devel.

Мы можем нарисовать такие коммиты, используя круглые o s, чтобы заменить действительные хеш-идентификаторы, хотя я должен теперь начать догадываться, как много коммитов у них есть, чего у вас нет.Перед запуском git fetch upstream у вас есть что-то вроде этого:

... <-o <-o <-o   <-- master
               \
                o   <-- defect-875

, где ваш defect-875 коммит указывает на кончик вашей ветви master, которая указывает на какой-то более ранний коммит, и такна.Как только вы запустите git fetch upstream, у вас будет что-то похожее на это:

                     o--o   <-- upstream/devel
                    /
             o--o--o   <-- upstream/master
            /
...--o--o--o   <-- master
            \
             o   <-- defect-875

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

Теперь вы можете объединить

Когда вы запускаете git merge, вы должны указать вашему Git , который обязуется объединиться с .Обычно вы делаете это, присваивая ему имя ветви или имя удаленного отслеживания, например upstream/devel.Это имя преобразуется в хеш-идентификатор фиксации - вы можете запустить git rev-parse, чтобы посмотреть, как это работает, как я показал выше.Он работает , потому что git fetch получил их devel и переименовал в свои собственные upstream/devel.Если вы еще не запустили git fetch upstream, вы должны сначала сделать это, чтобы ваш Git получил свои коммиты и переименовал их в devel, чтобы стать вашим upstream/devel.

Merging

На этом этапе вся работа выполняется в вашем собственном хранилище. Допустим, мои рисунки были точными;но давайте упростим это только для интересных имен и добавим слово HEAD к тому, которое вы сейчас отметили.Я также добавлю однобуквенные имена для трех интересных коммитов:

                     o--R   <-- upstream/devel
                    /
             o--o--o
            /
...--o--o--B
            \
             L   <-- defect-875 (HEAD)

Выполнение git merge upstream/devel найдет ваш текущий или HEAD коммит L (для левого или локального или --ours);ваш коммит помечен как upstream/devel, то есть коммит R (для правого или удаленного или --theirs);и используйте L и R, чтобы вернуться к общей начальной точке, которая является коммитом B (для базы).

Затем ваш Git, по сути, выполнит две команды git diff,чтобы увидеть, что вы изменили - что отличается в B против L - и посмотреть, что они изменили, т. е. что отличается в B против R:

git diff --find-renames <hash-of-B> <hash-of-L>   # what we did
git diff --find-renames <hash-of-B> <hash-of-R>   # what they did

Git теперь объединяет - объединяет - эти два набора изменений.Если они легко комбинируются, Git применяет объединенные изменения к снимку, связанному с коммитом B, и создает новый коммит из результата.Это коммит слияния , особый вид коммита.Что делает его особенным, так это просто то, что у него два родителя вместо одного: сначала он перечисляет ваш собственный коммит L в качестве первого родителя, а затем их коммит R в качестве второго родителя.

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

             L----------------M   <-- defect-875 (HEAD)
            /                /
...--o--o--B                /
            \              /
             o--o--o      /
                    \    /
                     o--R   <-- upstream/devel

Этот новый коммит M существует в вашей собственной ветке defect-875.

Отправка новых коммитов в upstream

Теперь вы можете, если у вас есть права доступа, использовать git push to create a defect-875 ветку в репозитории Git, которую ваш Git называет upstream, используя:

git push upstream defect-875

Это заставляет ваш Git вызывать их Git, предлагать им список коммитов, которые у вас есть, которые у них нет - что в данном случаеровно два коммита L и M - и затем предлагают своим Git создать ветку с именем defect-875, используя коммит M в качестве его коммитного наконечника.

Если они подчиняются всем этим запросами предложения, ваш Git будет помнить, что они сделали это, и добавить к вашему собственному набору имен, имя upstream/defect-875:

             L----------------M   <-- defect-875 (HEAD), upstream/defect-875
            /                /
...--o--o--B                /
            \              /
             o--o--o      /
                    \    /
                     o--R   <-- upstream/devel

Ваша собственная ветка defect-875 никак не изменяется: вашимя defect-875 все еще идентифицирует ваш коммит M (по его фактическому хеш-идентификатору, что бы это ни было).Вы просто дали их Git эти два коммита, и их Git установили их имя defect-875 в соответствии с вашим.

Если вам нравитсяe, теперь вы можете установить upstream для вашей собственной ветви defect-875 на имя upstream/defect-875:

git branch --set-upstream-to=upstream/defect-875 defect-875

Если вы хотите сделать и то и другое при запуске git push, вы можете сделать все сразу, добавив флаг -u к вашему git push:

git push -u upstream defect-875

но это всего лишь оптимизация удобства.

0 голосов
/ 12 сентября 2018

Я думаю, вы должны сказать git merge upstream/devel -m "Merging from devel" (проверив дефект-875, просто чтобы мы оказались на одной странице).

...