Идентификация фактических названий веток git коммитов - PullRequest
0 голосов
/ 24 августа 2018

enter image description here

Это простой репозиторий git.Я пометил коммиты номерами для удобства ссылок.Репо имеет следующие филиалы:

  • master: 13 коммитов (1,2,3,4,5,6,7,8,9,10,11,12,13) ​​
  • new_branch: 8 коммитов (1,2,3,4,5,6,14,15)
  • test_branch: 3 коммитов (1,2,3)
  • still_another_branch: 14коммиты (1,2,3,4,5,6,7,8,9,10,11,12,16,17)

Фиксация 5,6 относится к запросу на извлечение, поэтомусиняя часть с 5,6 не является ветвью.

Обратите внимание, что коммит 1,2 рассматривается как часть всех ветвей, но я хочу рассмотреть все коммиты черного цвета как часть мастера.Аналогично, для 'test-branch' я хочу рассмотреть только коммит 3 как часть ветви.

from git import Repo

git_url = "https://github.com/unimamun/test-repo.git"
repo_dir = "/mnt/hdd/aam/J2_Repos/test-repo/test-repo"

repo = Repo.clone_from(git_url, repo_dir)

# get all commits by branches    
def get_commits(repo, ref_name):
    commits = []
    for commit in repo.iter_commits(rev=ref_name):
        commits.append(commit)
    return commits

print('\nCommits in Branches:')
for ref in repo.references:
    print(ref.name,': ', str(len(get_commits(repo, ref.name))))


print('\nCommits in master:')
commits = list(repo.iter_commits('master'))
commits.reverse()
i = 0
for commit in commits:
    i += 1
    print(i,': ', commit.hexsha)

    # to see parents of the commit 
    #print('Parents: ',commit.parents)

Из приведенного выше кода у меня есть следующий вывод:

Commits in Branches:
master :  13
origin/HEAD :  13
origin/master :  13
origin/new_branch :  8
origin/test-branch :  3
origin/yet_another_branch :  14

Commits in master:
1 :  694df9fee2f9c03a33979725e76a484bce1738a0
2 :  c0fe1b76131b7fcb103f171fd93d85cda17b756c
3 :  0199ad335f65d52a2895a678a19e209e1e16a1a7
4 :  dd0903259b0aadbf2d8fb00e566eee014264f7c0
5 :  7ed55c51e2527f47bc6344cd960ff5beb90cc65d
6 :  d10f19c85fbc1c27b7719a2dc64989255697181d
7 :  c41bdfaeae1f801776420ce161ca2555dffc5aad
8 :  56b5d6e1831a477c79e0fd336acc96ca266d5dea
9 :  6305a72d4e257ebe74b10ca538906f1eceb091bf
10 :  4c5d1ebe5f2f8168ee8bf4a969855821d04caf09
11 :  362bc52be00af3fb917196cf27a8ddc0bb8fd4ba
12 :  5a70a46394eb08b4b48f9eb05798048ca7269a9d
13 :  f4a8bdd318b2678191d06616a55df26416a28363

Я хочу следующий вывод.Таким образом, «мастер» печатается для каждой черной точки на рисунке и других имен ветвей для фиксаций не черного цвета (в этом случае для фиксации 3 зеленого цвета должна быть напечатана тестовая ветвь)

Commits in master:
1 :  694df9fee2f9c03a33979725e76a484bce1738a0 master
2 :  c0fe1b76131b7fcb103f171fd93d85cda17b756c master
3 :  0199ad335f65d52a2895a678a19e209e1e16a1a7 test-branch
4 :  dd0903259b0aadbf2d8fb00e566eee014264f7c0 master
5 :  7ed55c51e2527f47bc6344cd960ff5beb90cc65d master
6 :  d10f19c85fbc1c27b7719a2dc64989255697181d master
7 :  c41bdfaeae1f801776420ce161ca2555dffc5aad master
8 :  56b5d6e1831a477c79e0fd336acc96ca266d5dea master
9 :  6305a72d4e257ebe74b10ca538906f1eceb091bf master
10 :  4c5d1ebe5f2f8168ee8bf4a969855821d04caf09 master
11 :  362bc52be00af3fb917196cf27a8ddc0bb8fd4ba master
12 :  5a70a46394eb08b4b48f9eb05798048ca7269a9d master
13 :  f4a8bdd318b2678191d06616a55df26416a28363 master

Мне нужно перебрать коммит с 1 по 13 и по пути мне нужно определить, какой коммит принадлежит какой ветке.Большое спасибо.

Ответы [ 2 ]

0 голосов
/ 24 августа 2018

Возможно, вы захотите попробовать опцию "--first-parent":

git log --oneline --first-parent master

С точки зрения математики, это график, из-за которого в точке слияния ни одна ветвь не считается "более важной".чем другой.Но на самом деле проблема всегда возникает, и при выполнении операции «слияния» фактически «переносится» внешняя ветвь в текущую.Следовательно, эта текущая ветвь указывается как первая в коммит-объекте.

Если вы попробуете это в основной ветке большого проекта, такого как ядро ​​linux, вы в основном попадете на точки слияния, только снесколько прямых наборов изменений в ветви.

И если это именно то, о чем вы хотите знать, вы можете дополнительно указать "--no-merges", чтобы явно исключить точки слияния.

git --oneline --first-parent --no-merges master

Это, например, исключило бы точки 4 и 7 из вашего графика.

Наконец, чтобы ограничить поиск фиксациями, которые принадлежат только определенной ветви и которыене наследуются от главного, используйте оператор "..":

git log master..yourbranch

… будет показывать только те коммиты, которые доступны из "yourbranch", но НЕ из "master".

0 голосов
/ 24 августа 2018

Как вы заметили:

коммит 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: обходит базу данных, чтобы найти все объекты, затем выполняет операцию сборки мусора с разметкой и уборкой, как это делал бы Лисп, сохраняя достижимые объекты и отбрасывая недоступные.

...