В ветке git я храню SHA последнего хэша коммита, используя
latest_sha=$(git log --pretty=oneline | head -1 | cut -d ' ' -f 1)
После кучи коммитов в этой ветке, как мне получить SHA следующего коммита после last_sha.
Скажем, если в этой ветке было сделано 5 коммитов после $latest_sha.
Я хочу всегда получать SHA первого коммита после last_sha.
b8eead8ba4ff375911af6
c2452680eb7731e4d36ca
da2e113ca4768f5f34730
95b98d42a6e567ed56fc2
716c4f84a855f48bee55c
6a7223a74269f925cfd9e---I need this one
e945bcfabf3fbafc85084---latest_sha
159df375376ded565bec0
d725350982626f46a8b80
56a4b6ca91d93acc8d751
de584608616b1ed99a554
3cfc15339a98bb286d5baa
6ae834bf36c90fbd81854
fa9bdebd0f814f04ee05ba
cc44c4d9ff14314c1255da
5a6145586a8fdcaa2da659
bfea8cfe121d24a0ff1525
Спасибо!
Вы можете сделать это с помощью rev-list
:
git rev-list --ancestry-path HEAD ^${latest_sha} | tail -n1
rev-list
перечисляет все доступные коммиты в обратном хронологическом порядке для заданных веток/коммитов. Знак вставки (^
) здесь означает «нет», что заставляет Git исключать все достижимые коммиты, начиная с данного коммита.
Конкретно это означает: включить все коммиты, доступные из HEAD
, исключить все коммиты, доступные из ${latest_sha}
, а затем взять самые старые коммиты, используя tail
.
Обновлено: добавьте --ancestry-path
, чтобы убедиться, что используются только те коммиты, которые находятся на прямом пути предков между указанными коммитами (как упоминалось @jthill).
Журналы git имеют родительское поле фиксации, поэтому вы можете сделать что-то вроде
git log --pretty=format:"%P %H" | awk '$1 == "<YOUR_HASH>" {print $2}'
Имя ветки Git, в некотором смысле, является последний хэш-идентификатор. То есть, если git log branchX
показывает, что вы сначала фиксируете b8eead8ba4ff375911af6
, то branchX
— это имя, представляющее b8eead8ba4ff375911af6
, и:
git show branchX
покажет ту же фиксацию, что и:
git show b8eead8ba4ff375911af6
Если вам по какой-то причине нужен хэш-идентификатор — например, потому что вы собираетесь изменять — хэш-идентификатор, на который указывает имя ветки, путем добавления новых коммитов — самая простая команда для его получения — git rev-parse
:
hash=$(git rev-parse refs/heads/$branch)
Для остальных см. ответ альфункса. Обратите внимание, что если коммиты образуют ромбовидный график, например:
I--J
/ \
...--G--H M--N <-- branchX
\ /
K--L
тогда есть коммиты два, которые следуют сразу за H
, но либо I
, либо K
являются предками друг друга, они связаны только тем, что оба являются потомками H
и предками (в данном случае прародителями) коммита слияния M
. При использовании git rev-list --ancestry-path ^<anything-identifying-H> <anything-identifying-branchX>
будут перечислены коммиты I
, J
, K
, L
, M
и N
. Список начнется с N
и вернется к M
в качестве второй записи, но на данный момент у Git теперь есть выбор: отображать J
или L
. Здесь вступают в силу выбранные вами параметры сортировки. Сортировка по умолчанию осуществляется в хронологическом порядке по отметке даты и времени коммиттера.
Перечислив либо J
, либо L
, Git теперь может перечислить родителя любой фиксации, которую он указал, или оставшуюся фиксацию на другом форке истории. Git перечислит один из них. Если он решил сначала перечислить J
, затем I
, теперь он должен перечислить L
, а затем K
в этом порядке; если он решил сначала перечислить L
, затем K
, теперь он должен показать I
, а затем J
в этом порядке. Но он также может перечислить их в порядке, например, J
, L
, K
, I
; или J
, L
, I
, K
. Добавление --topo-order
ограничений git rev-list
, чтобы избежать чередования коммитов с двух сторон.
Порядок линеаризации в сложных графах, как правило, проблематичен: не существует единого решения для всех случаев. Вот почему git rev-list
предлагает несколько вариантов сортировки.
Это не обязательно найдет дочерний элемент этой фиксации, добавьте
--ancestry-path
, чтобы перечислить только потомков. Если, например, ваш коммит является родителем слияния, другой родитель этого слияния мог быть написан после вашего.