Они не (перевернутые). Скорее, ..
в git diff
имеет специальное значение, которое имеет значение no , а ...
в git diff
имеет специальное значение, уникальное для git diff
, не встречающееся ни в одной другой команде Git. .
Ваш конкретный входной график - это ... был , до редактирования :-) ... слишком мал, чтобы показать реальную разницу. Если у вас было больше коммитов после того, как две ветви разошлись, вы могли бы увидеть больше.
Long
Давайте сначала посмотрим на git diff
, потому что это проще. Что git diff
делает в этих конкретных случаях - есть особые случаи для комбинированных различий , но они здесь не применяются; и мы можем различить коммит против нашего рабочего дерева или против нашего индекса, который мы здесь не делаем - это выбрать два отдельных коммита и сравнить их .
Чтобы назвать два коммита для сравнения, я предпочитаю написать:
git diff <commit1> <commit2>
Однако вы можете, если хотите, написать:
git diff <commit1>..<commit2>
Это означает точно то же самое , всегда. 1 Git просто делает вид, что вы не написали ..
в конце концов. Это верно, используете ли вы здесь хэш-идентификаторы, или имена ветвей, такие как master
, или имена для удаленного отслеживания, такие как origin/master
, или любое их сочетание.
Обратите внимание, что порядок двух имен-или-хеш-идентификаторов коммитов имеет значение: вывод git diff
представляет собой набор инструкций, сообщающих вам, как изменить первый коммит, чтобы получить второй коммит, если Вы следовали всем инструкциям.
Если вы напишите:
git diff <commit1>...<commit2>
Git будет все еще сравнить два коммита: 2 Git найдет базу слияния между двумя данными коммитами, затем сравнит этот базовый коммит слияния со вторым указанный коммит. То есть это то же самое, что и расширение в стиле оболочки:
git diff $(git merge-base <commit1> <commit2>) commit2
Здесь, как и прежде, порядок имеет значение: база слияния одна и та же, 3 независимо от порядка двух коммитов, но эта база слияния сравнивается со вторым в списке коммитом.
1 Ну, почти всегда! Есть несколько угловых случаев, которые вы можете отметить, если вы перечислите третий коммит в командной строке, где он действует так, как если бы вы использовали трехточечный синтаксис. Я бы сказал, что это ошибка в git diff
, хотя всегда возможно, что кто-то зависит от них.
2 Здесь есть еще один угловой случай, и он определенно является ошибкой: если имеется более одной базы слияния, git diff
создает комбинированный diff. Это не цель трехточечного синтаксиса, поэтому это ошибка.
3 Предполагается, что вы не отметите ошибку в сноске 2. Если для нескольких коммитов существует одна база слияния, порядок не имеет значения, но при наличии нескольких баз слияния порядок входы могут влиять на порядок выходов.
Для git log
и большинства других команд Git, однако, ..
и ...
имеют совершенно другое значение. Как вы, без сомнения, знаете, <commit1>..<commit2>
- это сокращение от <commit2> ^<commit1>
. Мы можем видеть это с git rev-parse
:
$ git rev-parse master..origin/maint
468165c1d8a442994a825f3684528361727cd8c0
^ccdcbd54c4475c2238b310f7113ab3075b5abc9c
Здесь origin/maint
переводится в первый (неотрицательный) хэш-идентификатор, а master
переводится во второй (отрицательный). Они сообщают Git, что во время обхода графика коммитов он должен выбирать коммиты, которые достижимы из 468165c1d8a442994a825f3684528361727cd8c0
(положительная ссылка), а отклонять коммиты, которые достижимы из ccdcbd54c4475c2238b310f7113ab3075b5abc9c
(отрицательная ссылка). Это означает все таких коммитов, которых может быть много. Команда типа git log
, проходящая по графику фиксации, покажет все выбранные фиксации.
Трехточечная запись сложнее, но внутренне переводит на один и тот же тип положительной и отрицательной ссылки:
$ git rev-parse master...origin/maint
468165c1d8a442994a825f3684528361727cd8c0
ccdcbd54c4475c2238b310f7113ab3075b5abc9c
^468165c1d8a442994a825f3684528361727cd8c0
Здесь две положительные ссылки - это идентификаторы хеша, связанные с origin/maint
и master
, как и раньше, а отрицательная ссылка - это результат точки (точек), в которой подграфы, выбранные этими начальными точками, воссоединяются. В этом конкретном случае есть только одна такая точка - так что это соответствует выводу git merge-base
, как мы увидим через мгновение - хотя некоторые подграфы, которые расходятся и объединяются сложным образом, могут иметь несколько таких точек:
$ git merge-base master origin/maint
468165c1d8a442994a825f3684528361727cd8c0
(Это те же самые сложные графы, которые могут привести к нескольким базам слияния, хотя код, реализующий ...
, проще, чем код, который находит базы слияния.)
Если у вас есть такой график:
C--D <-- br1
/
A--B
\
E--F <-- br2
синтаксис из трех точек br1...br2
выбирает коммиты C-D
и E-F
для команд, которые идут по графику, как git log
, но выбирает коммиты B
и F
соответственно для git diff
(и только для git diff
). Синтаксис из двух точек br1..br2
выбирает коммиты E-F
для git log
и т.п. и сравнивает коммиты D
и F
соответственно для git diff
(и только для git diff
) .