TL; DR
Это может быть совершенно нормально.Например, возможно, базовая версия также имеет 1050 строк, и одно из изменений заключается в delete 50 строк.Сочетание «удалить 50 строк» с «изменить что-то другое или вообще ничего не менять» приводит к «удалению 50 строк» в качестве окончательного изменения, внесенного в этот файл.
Что следует знать перед объединением
Есть несколько вещей, которые нужно помнить о слиянии в Git.Прежде всего, Git использует слияние как глагол, для слияния , что означает для объединения изменений , и что Git также использует слияние как прилагательное или существительное, слияниеcommit или просто слияние , которое относится к коммиту, в котором есть как минимум два родительских коммитов.
Еще один факт: git merge
не всегда на самом делеслияния.Вместо этого он может делать то, что называется fast-forwarding .В этом случае Git вообще не выполняет форму глагола - здесь не происходит слияния - и не делает коммит слияния.Поэтому убедитесь, что ваше слияние является реальным слиянием, которое я опишу ниже, а не одним из этих быстрых пересылок вместо этого.
Помните также, что Git хранит снимки: каждый коммит является полной копией каждый исходный файл.Это влияет на то, как работает форма глагола для объединения .
«Объединять» не означает «копировать»
Объединение как глаголакт объединения изменений с некоторой общей точки .Чтобы подумать об этом, подумайте о двух людях, которые вносят два разных изменения: Алиса исправляет строку 12, где слово «с ошибками» написано с ошибками, а Боб исправляет строку 20, где в предложении есть неверное слово.Алиса исправляет свое орфографическое исправление, а Боб исправляет свое неправильное слово.
Когда Алиса собирается объединить исправление Боба или наоборот, Git не должен забирать другое исправление.Поэтому слияние этих двух изменений в файле README.txt
должно сравнить версию Алисы с версией слияния , а затем сравнить версию Боба с той же версией слияния.Независимо от изменений, внесенных Алисой, включается набор изменений: список «что изменила Алиса».Любые изменения, внесенные Бобом, переходят в отдельный набор изменений: то, что Боб изменил.
Git, затем объединяет два набора изменений, применяя оба набора изменений к базовому файлу, чтобыполучить окончательный результат.Если Алиса и Боб вносили свои изменения в разные строки - как в этом примере - Git просто принимает оба набора изменений.Если они изменили одинаковые строки, Git проверит, сделали ли они одно и то же изменение для этих строк, и если да, возьмите одну копию этого изменения.В противном случае (они изменили те же строки, но по-разному) Git объявляет конфликт слияния, оставляя you , чтобы исправить ситуацию.
Когда результат слияния вас удивит, проверьте ваши предположения
Первое, что нужно сделать, это убедиться, что вы получили настоящее слияние.Если это так, то следует выяснить, какой была общая базовая версия .Вы можете сделать это, используя команду git merge-base
:
git merge-base --all a1fc931 4056ca3
, например, если две хеши фиксации, которые вы объединяли, были a1fc931
и 4056ca3
.Чтобы найти хеши коммитов, вы можете посмотреть git log --graph --oneline
;или, если слияние завершено, вы можете использовать специальный синтаксис Git для работы с родителями слияния, которое вы только что сделали:
git merge-base --all HEAD^1 HEAD^2
Если слияние остановилось из-за конфликта слияния, вы можете найтибазы слияния следующим образом:
git merge-base --all HEAD MERGE_HEAD
, поскольку MERGE_HEAD
будет записывать хэш другого коммита.
Найдя базу слияния - это будет большой уродливый идентификатор хеша - теперь вы можете произвестидва набора изменений, которые видит Git:
git diff --find-renames <base> <left>
git diff --find-renames <base> <right>
The <base>
вот хеш-код базы слияния, найденный git merge-base --all
.(Если было найдено более одного, вы оказались в особом случае, который становится более трудным; если повезет, он напечатал только один хэш-идентификатор.) Часть <left>
имеет значение HEAD^1
или HEAD
, в зависимости от того,слияние завершено: это коммит, на котором вы были, когда начали слияние.Часть <right>
- это другой коммит, который либо HEAD^2
, либо MERGE_HEAD
.
. Вывод двух git diff
s равен , что вы изменили (слева) и что они изменили (справа).Git объединяет эти изменения или объединяет их, чтобы произвести слияние или сбой.
Еще несколько слов (и диаграмма) об основах слияния и быстрой пересылке
Акт поиска базы слияния в Git состоит в сканировании через граф коммитов - или столько, сколько нужно - чтобы найти младшего общего предка из двух коммитов, являющихсяслиты.Если мы рисуем график с более ранними коммитами слева, а более поздними коммитами справа, например:
o--o--L <-- yourbranch (HEAD)
/
...--o--*
\
o--o--R <-- otherbranch
, где каждый раунд o
представляет коммит, то base merge - это первый коммит, при котором две ветви в прошлом объединяются: в данном случае, коммит *
.Таким образом, Git будет сравнивать commit *
с коммитом L
и сравнивать *
с коммитом R
, чтобы выяснить, что вы изменили и что они изменили.
Быстрая перемотка происходит, когда ветвьпоследовательность выглядит примерно так:
...--o--* <-- yourbranch (HEAD)
\
o--o--R <-- otherbranch
Здесь базовый коммит слияния равен вашему текущему (HEAD) коммиту.Если бы Git сравнил коммит *
с коммитом *
, что бы изменилось?
В этом случае Git не должен выполнять никакого фактического слияния.Он может просто проверить фиксацию R
напрямую, потому что объединение «ничего не изменилось» с «тем, что изменилось между *
и R
» просто снова дает вам фиксацию R
.Таким образом, Git делает это по умолчанию, что приводит к:
...--o--o
\
o--o--R <-- yourbranch (HEAD), otherbranch
, и вы просто получаете их версию каждого файла.
Вы можете заставить Git выполнить реальное слияние и реальное слияниекоммит, в результате чего вместо этого:
...--o--*---------M <-- yourbranch (HEAD)
\ /
o--o--R <-- otherbranch
где M
- коммит слияния (слияние как прилагательное).Снимок , сохраненный в коммите M
, будет точно соответствовать снимку в коммите R
.Git объединяет ваши изменения "вообще без изменений" с их изменениями, применяет их к базе *
и создает новый коммит, соответствующий R
.