Как объединить две локальные ветви, когда git-merge и git-rebase говорят «Уже в курсе», но git-diff ясно показывает различия - PullRequest
0 голосов
/ 08 февраля 2019

У меня есть 2 ветви: feature-branch-a и feature-branch-b Я могу углубиться в подробности истории git этого локального репо, если хотите, но в итоге можно сказать, что feature-branch-a является исконной ветвью feature-branch-b.

Когда я git checkout feature-branch-b и я git merge feature-branch-a или я git rebase feature-branch-a, ничего не происходит, потому что это Already up to date.

Тем не менее, выполнение git diff feature-branch-a из feature-branch-b ясно показывает мой отредактированныйИзменения.

Пожалуйста, помогите мне перевести это в команду git:

Уважаемый git, у меня есть некоторые изменения в feature-branch-a, которые я хочу добавить в feature-branch-b.Я знаю, что это дополнение приведет к конфликту слияния.Пожалуйста, объедините эти изменения вместе с этими хорошими <<< === ... маркерами разрешения конфликтов </p>

Я просто хочу знать, как объединить любые две ветви, которые имеют разное содержание (согласно git diff) без ложного, смешного Already up to date сообщения.Спасибо:)

Ответы [ 2 ]

0 голосов
/ 08 марта 2019

В то время как @torek дал очень блестящий и обстоятельный ответ, я хочу немного позабавиться.Если вам удалось каким-либо образом испортить версии вашего файла, и вам кажется, что вам страшно неприятное сообщение " Уже в курсе ", даже когда diff ясно показывает различия (очень раздражает. СтопВранье !!), вы можете просто воспользоваться редактором Microsoft Visual Studio Code.

Существует это потрясающее расширение под названием GitLens , которое действительно подстегивает git для вас.Поэтому я решаю использовать это, когда испорчу свои версии файлов, или когда я просто хочу вручную выбрать изменения в одном или нескольких файлах.Расширение позволяет открывать файл из разных коммитов рядом друг с другом, и оно приятно выделяет различия в двух версиях, так что изменения можно легко вносить по мере необходимости.

Это просто экономит время (и волосы-сохранитель тоже: р))

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

Git не хранит изменения.Git хранит снимки.

Думайте об этом как о дневных высоких температурах.Предположим, я говорю вам только , что сегодня на несколько градусов теплее, чем вчера.Можете ли вы сказать мне, какая температура была вчера и сегодня?Если нет, то почему?Если я скажу вам только, что сегодня было 50˚F, было ли сегодня теплее, чем на прошлой неделе?Если вы не можете сказать мне, почему нет?Какая информация позволит вам предоставить абсолютных температур на каждый день, если вам дают только различия?Или, если вам дают только абсолютные температуры каждый день, как бы вы представили разницу между любыми двумя данными днями?

Подумав об этом, вы должны иметь четкое представление об «изменении» (дельта или разница:сегодня теплее, чем вчера, который мы вычитаем, вычитая два снимка) против «снимка» (вчера было X градусов, а сегодня Y, что позволяет нам получить снимок, только если у нас есть стартовый снимок для добавить это к), и как перейти от одного к другому.Так что теперь следующая часть будет иметь смысл: Чтобы перейти от снимков к дельтам, вы должны дать Git два конкретных снимка.

Итак, теперь давайте вернемся к вашей формулировке:

Дорогой мерзавец, у меня есть некоторые изменения в feature-branch-a ...

Чтобы иметь изменений , вы должны выбрать два снимка.Какие два снимка вы выбираете?

... которые я хочу добавить к feature-branch-b

После того, как вы выбрали два снимка в функциональной ветви A, выможет заставить Git превратить их в изменения (различия) и применить их к снимку в конце ветви B. Это не так уж сложно.Но вы бы хотели сделать это автоматически , и вот тут вы столкнетесь с проблемами:

... Суть в том, что feature-branch-a является исконной ветвью feature-branch-b.

Ветви не являются предками ветвей, не являются детьми и не имеют таких отношений.Или, ну, может быть, они и делают: проблема здесь в том, что мы не определили, что мы, или вы , обозначаем как «ветвь».См. Что именно мы подразумеваем под "ветвью"?

В Git ветвь name , как и feature-branch-a, просто определяет один конкретный коммит, тем самымуникальный хэш-идентификатор коммита. фиксирует имеет отношения предок / потомок, и на основе вашего описания и ошибки при выполнении git merge мы можем нарисовать эти отношения:

...--o--o--A   <-- feature-branch-a
            \
             o--o--...--B   <-- feature-branch-B

Я выбрал два особенно интересныхкоммиты здесь: commit A, чьи предки слева от него - безымянные круглые o узлы - и commit B, чьи предки являются коммитами слева от B, который включает в себя commit A.

То есть снимки, содержащиеся в feature-branch-A, представляют собой A, а коммиты, оставшиеся от A.Моментальные снимки, содержащиеся в feature-branch-B, представляют собой B, а оставшиеся - , включая A и оставшиеся A. Каждый коммит "в" или "в" ветви A уже находится в / в ветви B.

Если вы запустите:

git checkout feature-branch-b
git merge feature-branch-a

путь git mergeЧтобы выяснить, какие изменения нужно объединить, нужно найти лучшего общего предка между кончиком текущей ветви, т.е. коммитом B, и кончиком указанной вами ветви, т.е. коммитом A. лучший предок - тот, которого можно достичь из обоих коммитов , но в некотором неопределенном, но очевидном смысле ближайших к ним также.

Если вместо этого выглядело так:

          o--...--A   <-- branch-A
         /
...--o--*
         \
          o--...--B   <-- branch-B

, то база слияния будет коммитом с пометкой: она не только на обеих ветвях, она также близка к вамможет одновременно достигать A и B, в то время как является на обеих ветвях.(Коммиты слева от * также находятся на обеих ветвях, но находятся «еще дальше».)

Итак,Git может объединить их самостоятельно, сравнив - git diff -ing- * против A, чтобы увидеть, что они сделали, и * -vs- B чтобы увидеть, что вы сделали.Git может затем объединить свои улучшения - * -vs- A - с вашими, * -vs-B.Применение комбинированных изменений к * дает вам снимок с обоими наборами улучшений, объединяя обе линии работы во что-то, что готово зафиксировать как коммит слияния (немного особенныйвид коммита: тот, у которого два родителя вместо одного, но в остальном обычный снимок, как и при любом другом коммите).

Но с учетом вашей настройки:

...--o--o--A   <-- feature-branch-a
            \
             o--o--...--B   <-- feature-branch-B (HEAD)

Git обнаружит, что основой слияния является сам коммит A.Это на обеих ветках, и как можно ближе к A и как можно ближе к B.Так что Git будет отличаться A против A и обнаружит, что нечего объединять!

Это явно не то, что вы хотите.Но объединять нечего: кто бы ни сделал B , он начал с A и с тех пор добавил улучшений .Это все, что есть.Если вы хотите, чтобы Git удалил этих улучшений, вы можете сделать это, но не с git merge.

Если какой-то коммит, где-то между A и B, будет не В конце концов, это улучшение, вы можете сказать Git об этом:

...--o--o--A   <-- feature-branch-a
            \
             o--X--...--B   <-- feature-branch-B (HEAD)

Если коммит X ухудшает ситуацию, вы можете запустить git revert <hash-of-X>.Git превратит X в набор изменений - сравнивая его с родительским коммитом, расположенным слева от него на чертеже, - и попытается «не изменить» все в текущем коммите вотменить именно то, что было сделано в X.Это может быть успешным само по себе или может не получиться при конфликте слияния.(Внутри Git действительно делает git merge, используя X в качестве общей отправной точки, o слева от него в качестве другого наконечника ветвления и B в качестве вашего собственного наконечника ветвления. Это своего родасбивает с толку: может быть проще думать о нем, как о Git, просто «обращающем изменения». Слияние технически лучше, потому что оно обрабатывает некоторые более сложные случаи, но обычно это одно и то же.)

В конечном счете, тем не менее,ключом к пониманию этого является осознание того, что слияние не означает «сделай то же самое».Это означает, что объединяет изменения, начиная с общей начальной точки .Если у вас нет общей начальной точки, это сложно - современный Git не использует свой «режим угадывания», если вы не добавите --allow-unrelated-histories - и если начальной точкой является один из двух коммитов, объединять нечего.

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