Ваша фундаментальная ошибка заключается в том, что git merge
имеет два входа - вашу ветвь и некоторую другую ветвь. Это не тот случай: он имеет три входа, ни один из которых не является ответвлением . Три входа: совершает .
Давайте нарисуем некоторые коммиты и имена ветвей, которые помнят последний коммит, который идет в каждой ветке:
o--o--A <-- branch-A
/
...--o--*
\
o--o--B <-- branch-B
Если вы запустите git checkout branch-A
, вы получите commit A
, потому что имя branch-A
указывает на этот конкретный коммит. То же самое относится к git checkout branch-B
. Сравнение этих двух коммитов показывает некоторые различия в некоторых файлах. Это имеет значение, но не так уж много .
От коммита A
мы можем работать в обратном направлении (как и git log
) до безымянного коммита, затем другого безымянного коммита, затем коммита *
. С B
мы можем сделать то же самое, и если мы сделаем это, мы также получим commit *
. Поэтому коммит *
- база слияния предложенной операции слияния - это лучший общий коммит , лучший коммит, который находится на обеих ветвях.
Способ слияния заключается в запуске two git diff
s:
- Первый сравнивает снимок в коммите
*
с снимком в коммите A
, чтобы увидеть, что кто-то изменил на этом пути.
- Второй сравнивает снимок в коммите
*
со снимком в коммите B
, чтобы увидеть, что кто-то изменил на этом пути.
Затем Git объединяет эти два набора изменений. Полученные объединенные изменения, если они не конфликтуют, применяются к снимку из коммита *
.
Объединив два набора изменений и применив их правильно - или так правильно, как Git может определить - Git продолжает делать новый коммит, в основном обычным способом. Новая фиксация заставляет любую ветвь, которую вы извлекли (одно из двух имен ветки A или B), обновляться, чтобы указывать на новую фиксацию. Новый коммит имеет двух родителей, которые являются коммитами A
и B
. Итак, конечный результат:
o--o--A
/ \
...--o--* M <-- branch-<whichever> (HEAD)
\ /
o--o--B
с любым именем ветви не не двигалось, все еще указывая на A
или B
.
Снимок в новом коммите слияния M
соответствует *
, плюс оба набора изменений . Если A
не изменил что-то с *
, но B
изменил что-то с *
, вы получите B
изменения. Если A
что-то изменил, а B
- нет, вы получите A
изменения. Если оба изменили одинаковые строки одного и того же файла, , то вы получите конфликт слияния - и вы должны закончить задание слияния и сделать M
самостоятельно .
(Если файл C
находится в одном из A
и B
, но не в другом, файл C
должен быть либо создан, так как - *
, либо удален, поскольку - *
Объединение объединяет создание нового файла с ничем путем взятия нового файла. Он объединяет удаление старых файлов с ничем путем удаления старого файла Учитывая ваше текстовое описание, C
должен завершиться в *
, что дает вам действие удалить файл .)