Git merge сообщает: «Уже в курсе», коммиты находятся в главном, но изменения были существенно перезаписаны при следующем коммите - PullRequest
1 голос
/ 31 октября 2019

Вероятно, это дубликат, но я не могу найти ничего определенного для этой конкретной проблемы. Итак, пару недель назад я почти уверен, что я слил ветку в нашу главную ветку, в истории мастеров есть коммиты, но нет сообщения о слиянии, в котором говорится, что ветка была объединена. В истории при просмотре моих коммитов изменения явно присутствуют, но при просмотре файлов проекта при самой следующей фиксации изменений нет. Попытка git merge снова, конечно, выдает ошибки и говорит: «Уже в курсе», что технически да.

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

1 Ответ

1 голос
/ 31 октября 2019

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

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

(Имейте в виду, что различные зрители Git"сгладить" то, что по сути является запутанной историей, когда есть слияния, и может просматривать коммиты не по порядку. Добавьте --graph к вашей команде git log, если вы используете git log для просмотра коммитов, чтобы заставить git logотображать коммиты в порядке графа коммитов и рисовать грубый ASCII-график отношений коммитов.)

Каков наилучший способ внести эти изменения в основную ветку?

Best - вопрос мнений, но для easy вы всегда можете использовать git cherry-pick.

Способ работы git cherry-pick заключается в том, чтовы даете ему имя - например, необработанный идентификатор хеша - для фиксации. 1 Затем Git сравнивает этот коммит с его родителем (в единственном числе). Это сравнение между снимками «до» и «после» показывает, что изменило между двумя снимками, поэтому Git теперь может повторно применить те же самые изменения к любому коммиту, который вы только что извлекли.

Следовательно:

git checkout master
git cherry-pick <hash>

работает, чтобы скопировать эффект любого данного обычного коммита.

Если ваше слияние повлекло за собой эффект некоторого большого количества коммитов, вы, возможно, захотите git cherry-pick всего слияния. Непосредственным камнем преткновения является то, что коммит слияния имеет более одного родителя . Сам по себе git cherry-pick просто подбрасывает метафорические руки в воздух и сдается: он не знает, какого родителя использовать, сравнивая родителя с ребенком, чтобы увидеть «что произошло в этом коммите».

КакПравило, однако, правильный родитель для использования почти всегда родитель № 1. Если этот является правильным родителем, вы просто сообщаете это git cherry-pick, используя его опцию -m:

git cherry-pick -m 1 <hash>

Чтобы определить, является ли родительский номер 1 правильным коммитом для использования,вы можете сделать сравнение между родителем # 1 и данным коммитом:

git diff <hash>^1 <hash>

Суффикс ^1 сообщает Git: перейти от этого коммита к первому родителю . (См. Сноску 1 и документацию gitrevisions, снова.) Поэтому diff сравнивает снимок в родительском # 1 со снимком в hash. Результатом этого сравнения является набор изменений, которые git cherry-pick будет пытаться скопировать.

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

git diff <hash>^2 <hash>

. Это покажет разницу между вторым родителем и данным коммитом.


1 Подойдет любое имя;см. документацию gitrevisions для очень длинного списка способов присвоения коммитов. «Истинное имя» - это как бы необработанный хеш-идентификатор: он всегда работает и всегда называет один конкретный коммит. Единственный недостаток использования этого - то, что имя невозможно запомнить и трудно напечатать, но обычно легко вырезать и вставить идентификатор хеша, например, из git log.

...