Обратите внимание, что если существует только простой линейный путь от feature
до master
, вам хорошо с принятым ответом на Git - как найти первый коммит определенной ветви :
A--B--C--D <-- master
\
E--F--G <-- feature
Здесь git log --oneline master..feature
выведет список коммитов G
, затем F
, затем E
, поэтому последняя строка вывода будет для коммита E
.(Если вы просто хотите получить хеш-код, используйте git rev-list master..feature | tail -1
.)
Но учтите:
A--B--C--D <-- master
\
E <-- develop
\
F--G <-- feature
Здесь master..feature
все еще перечисляет коммит E
, даже если вы хотите коммит F
: вам нужно develop..feature
, чтобы иметь git log
список G
, затем F
и затем остановить.
Или:
A--B--C--D <-- master
\
\ F--G <-- feature1
\ / \
E J--K <-- feature3
\ /
H--I <-- feature2
Здесь, коммит B
является общимпо всем филиалам;commit E
есть на всех ветках кроме master
;F
и G
являются общими для feature1
и feature3
;H
и I
являются общими для feature2
и feature3
;и J
и K
являются исключительными для feature3
.
Используя master..feature3
, вы будете перечислять коммиты с E
по K
, но порядок из,в частности, от F
до I
можно изменить.(E
появится после всех четырех, F
не будет упомянуто до того, как G
будет перечислено, и H
не будет упомянуто до того, как I
будет внесено в список, но это все еще оставляет большое количество возможных заказов.) Вы можете выбрать порядок, в определенных пределах, используя различные элементы управления сортировкой;по умолчанию идет переход к дате коммиттера, когда есть * несколько возможных коммитов для git log
для генерации в этот момент.
В общем, Git работает, начиная с tip commit, какна который указывает одно из этих названий ветвей, и работает в обратном направлении.При достижении места, где есть соединение (например, коммит слияния J
), Git начинает идти по обоим путям одновременно.С git log
он печатает эти коммиты в некотором порядке на основе выбранного вами порядка сортировки.(В конце концов пути обычно сходятся, как в этом случае они делают при коммите E
. В этот момент git log
может возобновить выполнение одного коммита за раз.)
Все коммиты фиксированына месте, пока они существуют - вы можете нарисовать график немного по-другому, но родительский элемент E
всегда, например, B
- но names , имена ветвей, которые указывают наконкретные коммиты, все они могут быть перемещены: любое имя может быть перемещено в любое время, чтобы указать на любой конкретный коммит.Имена могут быть добавлены или удалены в любое время с одним предупреждением: если вы удалите все имена, которые позволят вам найти коммит, может быть очень трудно вернуть этот коммит. 1 В общем, команды Git и списки диапазонов Git, такие как A..B
и т. Д., Разрешают имена в коммиты, а затем используют график коммитов для выполнения своей работы. 2
1 Если git gc
выполняется в неправильное время, и у вас отключены повторные журналы или записи журнала слишком старые и устаревшие, сборщик мусора Grim может выбросить любой недоступный коммит.В этот момент фиксация действительно пропала, и даже знание ее хеш-идентификатора не спасет вас.
2 Основное исключение здесь - git diff
:если вы зададите диапазон git diff
, он будет обрабатываться так, как если бы вы дали ему два разных хеш-идентификатора коммита.То есть git diff A..B
вообще не идет по графику, он просто находит A
и B
и затем действует точно так же, как git diff A B
.Команда git diff
также имеет специальную обработку для трехточечного синтаксиса, A...B
.
git rebase
также приобрела особый случай для A...B
(с тремя точками) в синтаксисе --onto
.