GIT: получить все хэши объектов git блобов, добавленных в репозиторий посредством фиксации

Можно ли с помощью инструментов командной строки git получить список всех хэшей блобов git, которые были добавлены в репозиторий заданным хешем фиксации?

Я уже пробовал заархивировать это с помощью сантехнического инструмента git git-diff-tree. Может это неправильный подход. Ниже представлен лучший результат, который я мог получить до сих пор. Но документация (очень длинная справочная страница) не помогла выяснить, как именно нужно интерпретировать вывод.

$ git diff-tree --no-commit-id 2b53d04dbb7cd35d030ddc59b13c0836a87daeb7 
:100644 100644 03f15b592c7d776da37e3d4372c215b14ff8820f 6e0ed0b1ed56e9a35a3be52a9de261c8ffcccae8 M      file1.ts
:100644 100644 b5083bdb9c31005ebd16835a0f49dc848d3f387a 4b7f9e6624a66fec0510d76823303017e224c9d7 M      file2.ts
:100644 100644 368d64862e6aa2a0110f201c8a5193d929e2956d 0e51626a9866a8a3896489f497fbd745a5f4a9f2 M      file3.ts
:040000 040000 c332b1e576af0dbb93cc875106bc06c3de6b74c8 f7f3478a9b0eaac85719699d97e323563a1b102b M      some_folder

Отображают ли первый и второй хэши больших двоичных объектов git соответственно старый и новый объекты для измененного файла? В худшем случае я мог бы получить эту информацию, проанализировав вывод.

Моей основной целью было найти командную строку, которая работает следующим образом:

$ git <command> <option1> <option2> 368d64862e6aa2a0110f201c8a5193d929e2956d 
6e0ed0b1ed56e9a35a3be52a9de261c8ffcccae8 
4b7f9e6624a66fec0510d76823303017e224c9d7 
0e51626a9866a8a3896489f497fbd745a5f4a9f2 

Измените ниже в ответ на @torek

В ответ на ответ @torek я хочу быть более ясным в своих намерениях, потому что он абсолютно прав, указывая на то, что новое не обязательно новое.

Я планирую использовать git rev-list --reverse <branch>чтобы получить список всех коммитов в этой ветке в порядке фиксации. Затем я хочу посетить каждую фиксацию в этом порядке и собрать впервые увиденные хэши BLOB-объектов в этой ветке для каждой фиксации.

Конечный результат должен быть примерно таким:

C:368d64862e6aa2a0110f201c8a5193d929e2956d
B:03f15b592c7d776da37e3d4372c215b14ff8820f
B:4b7f9e6624a66fec0510d76823303017e224c9d7
B:c332b1e576af0dbb93cc875106bc06c3de6b74c8
C:5521a02ce1bc4f147d0fa39a178512476764dd66 
B:e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e
B:adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
C:a3db5c13ff90a36963278c6a39e4ee3c22e2a436
B:4888920a568af4ef2d2f4866e75b4061112a39ea
.
.
.

C: совершитьB: капля

Если это нелегко сделать, можно сделать два прохода. В первом проходе капли могут упоминаться несколько раз в разных коммитах по причинам, которые вы указали:

  • добавление файла с таким же содержимым в другой файл
  • файл имеет то же содержимое после того, как он был изменен

Затем я мог бы сделать второй проход, пропустив файл через awk '!x[$0]++'который удалит любые дубликаты. Это было бы не очень эффективно, но дало бы желаемый результат.

Надеюсь, теперь я ясно изложил свои намерения. Какие-нибудь мысли?

1 ответ

Решение

Можно ли с помощью инструментов командной строки git получить список всех хэшей блобов git, которые были добавлены в репозиторий заданным хешем фиксации?

Да и / или нет: вы должны точно определить, что вы имеете в виду под добавлением в репозиторий.

Предположим, например, что я начинаю с полностью пустого репозитория:

$ mkdir foo && cd foo && git init
Initialized empty Git repository in ...

Сейчас я создаю README.md а также git add это и зафиксировать:

$ echo for testing > README.md
$ git add README.md
$ git commit -m initial
[master (root-commit) 19278e9] initial
 1 file changed, 1 insertion(+)
 create mode 100644 README.md

README.md представляет собой большой двоичный объект и его хэш-идентификатор:

$ git rev-parse HEAD:README.md
43b18adf702be62761e3affd85c4c3ee5c396be7

Позже напишу новый файл:

$ echo for testing > newfile.txt
$ git add newfile.txt
$ git commit -m 'add new file'
[master 5521a02] add new file
 1 file changed, 1 insertion(+)
 create mode 100644 newfile.txt

Если мы посмотрим на этот коммит, мы увидим новый файл. Если мы посмотрим на это сgit show --raw мы увидим это в git diff-tree формат:

$ git show --raw
commit 5521a02ce1bc4f147d0fa39a178512476764dd66 (HEAD -> master)
Author: Chris Torek <chris.torek gmail.com>
Date:   Fri Oct 18 14:10:55 2019 -0700

    add new file

:000000 100644 0000000 43b18ad A        newfile.txt

Это похоже на каплю, добавленную в репозиторий, но подождите, есть что-то ужасно знакомое43b18ad:

$ git rev-parse HEAD:newfile.txt
43b18adf702be62761e3affd85c4c3ee5c396be7

Да, это тот же хэш-идентификатор, что иREADME.md:

$ git ls-tree -r HEAD
100644 blob 43b18adf702be62761e3affd85c4c3ee5c396be7    README.md
100644 blob 43b18adf702be62761e3affd85c4c3ee5c396be7    newfile.txt

Это один blob, но два файла. Это действительно недавно добавлено?

Если ваш ответ на вышеизложенный - "да, он новый, хотя и старый", вы можете ответить на второй вопрос. Если ваш ответ "нет, это не ново", как насчет фиксации, которая повторно вводит blob-объект, который был удален в предыдущей фиксации? Или, если два коммитятI а также J производится параллельно на двух ветках:

          I   <-- br1
         /
...--G--H
         \
          J   <-- br2

оба представляют один и тот же blob, который фактически добавляет его как совершенно новый, а какой просто дублирует другой?

В общем, если вам нужно все новое, вам придется пройти весь граф коммитов, проверяя дерево каждого коммита (см.git ls-tree -r), и выберите, какие коммиты будут первыми, введите идентификатор объекта большого двоичного объекта, которого еще нет в каком-либо более раннем (родительском и / или по дате и времени) объекте фиксации. Если вы хотите "только что добавлен в этот коммит как новый файл", проверьте фиксацию и ее родительские элементы, возможно, используяgit diff-treeили похожие. Обратите внимание, что у полностью нового файла есть режим "все нули" в его родительском элементе и буква статусаA (добавлено), в то время как файл, измененный из родительского, имеет статусную букву M(изменено) и два ненулевых хэша. Номинально удаленный файл - файл, который существовал в родительском, но больше не существует в дочернем - имеет статусное письмоD(удалено). Если вы включите обнаружение переименования, вы получитеRзначения статусов и индекса сходства; вы можете отключить это или, по крайней мере, установить 100% проверку на подобие.

Другие вопросы по тегам