Я думаю, что может происходить то, что мои две ветки идентичны в исходном коде, но имеют разные коммиты?
Да, это правильный диагноз, хотя вы можете подтвердить это с:
git log --left-right --boundary --decorate --oneline --graph
upstream/master...upstream/release
(все как одно, разбитое на несколько для целей публикации).
Помните, Git примерно фиксирует . Имена ветвей, например master
и release
, и имена удаленного отслеживания, например upstream/master
и upstream/release
, идентифицируют конкретную фиксацию. Мы говорим, что эти имена указывают на эти коммиты.
Также указывают на другие коммиты: в частности, каждая фиксация указывает на своего непосредственного родителя.
Когда у вас есть простая линейная последовательность таких коммитов, каждая из которых имеет свой собственный ha sh ID, заканчивающийся некоторым финальным ha sh ID, который мы можем назвать H
, мы можем нарисовать это следующим образом:
... <-F <-G <-H <-- master
имя master
содержит правильный ha sh ID: он позволяет вам (или Git, по крайней мере) легко найти правильный ha sh H
для последний коммит в цепочке. Другими словами, master
указывает на H
. Сам коммит H
содержит моментальный снимок - все ваши файлы, замороженные во времени, - а также необработанный sh идентификатор предыдущего («родительского») коммита G
, поэтому H
указывает на G
. Команда ha sh позволяет Git находить G
. Коммит G
содержит снимок и другой родительский-ha sh, F
, который позволяет Git находить F
и т. Д.
В этом случае у вас есть такая ситуация :
I--J <-- upstream/master
/
...--G--H
\
K--L <-- upstream/release
По какой-то причине 1 снимки в J
и L
совпадают, поэтому сравнение upstream/master
(фиксация J
) с upstream/release
(фиксация L
) не показывает разницы, независимо от того, в каком направлении вы используете для сравнения.
Здесь полезно знать, что:
git diff A..B
просто означает:
git diff A B
То есть, Git находит два рассматриваемых идентификатора ha sh, извлекает два замороженных снимка и сравнивает (различает) их. Вы видите информацию о том, что необходимо для изменения снимка, который находится в A
, на снимок в B
,
Но:
git diff A...B
не означает сравнить От A до B , а скорее найдите базу слияния между A и B и сравните этот снимок базы слияния с B . В этом случае, учитывая сделанный мной рисунок, который, вероятно, не совсем соответствует фактическому набору коммитов, который у вас есть, базой слияния upstream/master
и upstream/release
является фиксация H
, которая, как вы можете видеть, присутствует в обоих истории: вы найдете фиксацию H
, если начнете с J
и будете работать в обратном направлении, и вы также найдете фиксацию H
, если начнете с L
и будете работать в обратном направлении.
Итак, вот это будет отличать снимок в H
от снимка в зависимости от того, на какой коммит указывает имя, которое вы указали справа. Поскольку снимки в J
и L
совпадают, вы увидите одно и то же различие независимо от того, каким способом вы его запустите:
git diff upstream / master ... upstream / release
сравнивает H
против L
, а:
git diff upstream/release...upstream/master
сравнивает H
против J
, но они оба дают одинаковую разницу.
Если вы хотите истории для совпадения - история - это набор коммитов, найденных, начиная с имени, а затем работая в обратном направлении - вы должны:
- переместить
upstream/release
или - переместить
upstream/master
или добавить новую фиксацию слияния и переместить оба, как показано:
I--J
/ \
...--G--H M <-- upstream/release, upstream/master
\ /
K--L
например. Но все это осложняется тем фактом, что эти два имени являются именами удаленного отслеживания . Это не имена веток, .
Эти имена удаленного отслеживания принадлежат вам, поэтому вы можете их перемещать - но ваши Git автоматически перемещает их в соответствии с идентификаторами ha sh, хранящимися в некоторых других Git именах веток репозитория. Другой репозиторий Git - это тот, который ваш Git называет upstream
, а он имеет имена веток master
и release
. Вы бежите:
git fetch upstream
и ваш Git вызывает их Git, находит все новые коммиты, которых у вас нет (которые вам понадобятся), получает этих коммитов, а затем обновляет ваш upstream/*
имена удаленного отслеживания для хранения тех же идентификаторов ha sh, что и их имена ветки .
Следовательно, чтобы обновить имена удаленного отслеживания, правильный способ сделать это чтобы убедить их обновить их ветки имена. Затем вы просто запускаете git fetch upstream
, чтобы обновить свой, чтобы он соответствовал.
1 Наиболее вероятная причина, чтобы эти коммиты совпадали, как это, без фиксации слияния на месте, для кто-то использовал git merge --squash
или, возможно, щелкающую кнопку веб-страницы GitHub с надписью «squa sh and merge».