~ і ^ рухаються по батьках коміту, але по-різному:
~n- n кроків назад по першому батькові:HEAD~1- батько,HEAD~3- прапрадід;^n- n-й батько коміту. Має сенс для merge-комітів, у яких батьків два:HEAD^1- гілка, у яку зливали,HEAD^2- гілка, яку зливали.
D---E (feature)
/ \
A---B---C---M (main, HEAD)
HEAD~1 = HEAD^ = HEAD^1 = C
HEAD^2 = E
HEAD~2 = B
HEAD^2~1 = D
Для звичайного коміту з одним батьком HEAD~1 і HEAD^ однакові - різниця видна лише на merge-комітах.
Інші способи назвати коміт:
main@{yesterday} # де була main вчора (за reflog)
@{-1} # попередня гілка
@{u} # upstream поточної гілки
HEAD^{tree} # дерево коміту
:/fix invoice # останній коміт з таким текстом у повідомленні
v2.4.0^{commit} # коміт, на який вказує тег
Діапазони:
| Запис | Що означає |
|---|---|
A..B |
коміти, досяжні з B, але не з A |
A...B |
коміти, досяжні з A або B, але не з обох (симетрична різниця) |
^A B |
те саме, що A..B |
git log main..feature # що є у feature і ще не злито в main
git log feature..main # що з'явилося в main, поки ви працювали
git log --left-right --oneline main...feature # обидві сторони з позначками < і >
git log origin/main..HEAD # що ви ще не запушили
Пастка: .. і ... у git diff означають інше:
git diff A..B- те саме, щоgit diff A B: порівняння двох знімків;git diff A...B- зміни вBвід спільного предка зA. Саме так GitHub показує diff pull request-у: лише зміни гілки, без того, що за цей час з'явилося вmain.
Тому git diff main...feature - правильний спосіб побачити «що змінює моя гілка», а git diff main feature покаже ще й чужі зміни в main з протилежним знаком.