Как вы заметили:
коммит 1,2 рассматривается как часть всех ветвей
То есть набор достижимых коммитов из любой данной ветви, как определено, начиная с коммита в кончике ветви и работая в обратном направлении через направленный ациклический граф коммитов, всегда включает коммиты 1 и 2.
, но я хочу рассмотреть все коммиты черного цветакак часть мастера [ветка]
В этом случае начните с поиска графика всех коммитов.Как вы, вероятно, знаете, граф определяется как G = (V, E) , где V - это множество всех вершин, а E - это множество всехкромки.Git хранит данные вершины и ребра вместе в коммите: идентификатором коммита является его хеш-идентификатор, а его ребра (в действительности исходящие дуги, поскольку это ориентированный граф) являются его родительскими хеш-идентификаторами.
Далееиспользуйте имя, которое вы хотите обозначить как «самую важную» ветвь (т. е. master
), чтобы найти хэш-идентификатор своего коммит-подсказки.Назначьте этот коммит на основной набор.Пройдите по доступной части графика, начиная с этого коммита, добавляя каждый коммит к набору коммитов в master
.
Теперь для каждой оставшейся ветви - в некотором порядке, и этот порядок будет определять ваши результатыво многих случаях, возможно, вы захотите использовать топологическую сортировку - начните с кончика ветви и пройдитесь по достижимой части графика:
- Для любого коммита, который уже назначен какой-либо ветви,игнорируйте его - и вы можете немедленно прекратить обход графика на этом этапе, так как все его предшественники, по определению, будут назначены на какую-то ветку.
- Множество коммитов, которые вы достигли во время этого обхода, это набор коммитов, которые выВы хотите заявить, что «принадлежите» этой ветке.
Существует несколько способов реализовать это, включая обход субграфа, определенного с помощью вычитания-набора: просто вычтите подграф каждой ветви из исходного G .
Если это удобнее - вполне может быть, поскольку вам не нужно будет искать G -Вы можете сделать это в другом направлении: начните с master
и найдите достижимые коммиты, которые не находятся в некотором наборе, который изначально пуст.Добавьте каждый коммит в набор, перечисляя их как «в мастере».Затем выполните итерацию по оставшимся ветвям: если коммит находится в наборе до сих пор, он уже был востребован, иначе он получает эту ветку.Проблема с такой работой заключается в том, что вы можете выбрать некоторую ветвь (feature-X
), которая содержит все коммиты, содержащиеся в какой-то другой ветке (develop
), прежде чем выбрать меньшую ветвь (develop
): вы не можете сделать топологическуюсортировка без полного графика.
После того, как вы сделали это для всех подсказок ветвления, вы теперь назначаете каждый коммит достижимости из ветки-подсказки одной ветке (вместо того, как это делает Git,это к каждой ветви, из которой она достижима.
Обратите внимание, что в графе Git могут существовать коммиты, которые не достижимы ни из одного кончика ветви (например, достижимы из тега, ноне из ветки).Если вы покопаетесь во внутренностях Git, вы сможете найти коммиты, которые доступны только из reflog записей или даже тех, которые полностью недоступны, обнаруживаются только путем перебора всей базы данных значений ключей объекта.Последнее, по сути, то, что делает git gc
: обходит базу данных, чтобы найти все объекты, затем выполняет операцию сборки мусора с разметкой и уборкой, как это делал бы Лисп, сохраняя достижимые объекты и отбрасывая недоступные.