Есть ли способ показать граф журнала git из HEAD для коммита, который был сделан конкретным пользователем? - PullRequest
0 голосов
/ 07 декабря 2018

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

Мне было интересно, смогу ли я либо:

  1. Получить последнюю запись журнала (или n записей журнала) из того места, где я сейчас нахожусь в репо, совершенном этим автоматическим пользователем, и / или
  2. Показать график из HEADк тому же автоматическому коммиту пользователя, который показывает все коммиты пользователей, которые были сделаны между ними.

Возможно ли либо просто использовать команды git, либо мне нужно выполнить некоторую внешнюю обработку?

Ответы [ 2 ]

0 голосов
/ 07 декабря 2018

Получить последнюю запись журнала (или n записей журнала) из того места, где я сейчас нахожусь в репо, который был зафиксирован этим автоматическим пользователем

Рассмотрим --author или --committerопция git log для этого:

--author=<pattern>, --committer=<pattern>

Ограничить вывод коммитов теми, у которых строки заголовка автора / коммиттера соответствуют указанному шаблону (регулярное выражение).С более чем одним --author=<pattern> выбираются коммиты, автор которых соответствует любому из заданных шаблонов (аналогично для нескольких --committer=<pattern>).

Итак, чтобы показать последние 5 коммитов на that-user наветку, которую вы в данный момент проверили, вы можете сделать

git log --pretty=fuller --author='that-user' -5
0 голосов
/ 07 декабря 2018

Редактировать: я добавил некоторый (длинный) фон ниже для общей полезности.

(Чтобы найти коммиты, сделанные определенным пользователем, используйте --author=. Это работает с большинством ревизий-ходячие операции, так как они реализованы git log и git rev-list, и другие команды Git используют их.)

Рассмотрите возможность использования git log --ancestry-path --graph <em>[options]</em> <em>automated-commit</em>..HEAD, но с некоторыми оговорками:

  • Возможноне be путь между автоматической фиксацией и HEAD фиксацией.
  • Если есть путь, он может пойти другим путем, если фиксация HEAD находится позади автоматическойcommit.

Обратите также внимание, что Git пропустит фиксацию границы (точки останова), то есть в A..B Git действительно выполняет B ^A, поэтому он включает в себя фиксацию B, ноисключает коммит A.Если вы также хотите включить коммит A, у вас есть несколько вариантов:

  • Резервное копирование одного коммита для остановки: используйте ^A^, предполагая, что A имеет только одинparent или ^A^@, если A может быть коммитом слияния (A^@ означает «все родители A», а ведущим ^ является расширение формы A..B до внутренней формы B ^Aдля общности здесь).

  • Или, используйте --boundary, чтобы Git включал граничные коммиты. Git имеет тенденцию добавлять слишком много граничных коммитов, по моему опыту, но --ancestry-path может устранить этопоскольку --ancestry-path увеличивает обычный A..B, требуя, чтобы отображаемые коммиты имели A в качестве предка.

(Итог: это должно работать, пока существует путь иВы получаете правильный заказ. Делать его действительно полезным и обрабатывать различные крайние случаи сложнее.)

Справочная информация: как git log и его сестра git rev-list работают

коммитов, вGit, известны и найдены по их истинным именам, которые являются их хэш-идентификаторами.Хэш-ID каждого коммита представляет собой большую уродливую строку, такую ​​как 8a0ba68f6dab2c8b1f297a0d46b710bb9af3237a (что является коммитом в репозитории Git для самого Git .) Каждый ID уникален: ни один другой коммит никогда не может иметь этот ID.Они на самом деле не случайные, но они кажутся случайными и бесполезны для людей, поэтому мы используем такие имена, как master и develop.Git постоянно обновляет таблицу, в которой, например, master означает 8a0ba68f6... и т. Д.

Используя эти записи в таблице, мы говорим, что master указывает на некоторый коммит.Допустим, master указывает на некоторый коммит, чей ID хеша мы сократили до одной заглавной буквы, G:

G   <--master

(через мгновение вы поймете, почему я поставил master вправо).

Добавление нового коммита в ветку просто обновляет сопоставление имени с хеш-идентификатором: вы создаете новый коммит, Git назначает ему уникальный хэш-идентификатор, и если вы включены master, Git обновляет запись таблицы для master для хранения этого нового хэш-идентификатора:

H   <--master

Это означает, что фиксация, на которую указывает какое-либо имя ветви - стрелка, хранящаяся в имени ветви - меняется со временем.Вот как Git находит последний коммит для этой ветки.По определению, любой хеш коммита сохраняется для этого имени ветви, этот коммит является вершиной этой ветки.

Теперь каждый коммит также содержит некоторое количество parent идентификаторы хеша - обычно ровно один.* * * * * * * * * * * * * * * * * * * * * * * * * * *} * * * * * * * * * * * * *} * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 10 * * * ”[110] * *1104* * 'мой родитель * 0f987... 110 6 *, Git знает, чтоa1234... - это последний коммит на мастере.Затем Git читает commit a1234..., чтобы найти второй-последний коммит на master, который равен 0f987....Так что master указывает на последний коммит, a1234..., и этот коммит указывает на его родителя, а его родитель указывает на деда и т. Д.

Это означает, что, начиная с конца , Git может работать в обратном направлении через цепочку коммитов:

... <-F <-G <-H   <--master

ThИмя master позволяет Git найти коммит H, который находит коммит G, который находит F и т. д. в обратном направлении по истории. History - это просто строка всех коммитов, начинающихся в конце и работающих в обратном направлении.

Специальное имя HEAD обычно содержит имя ветка .Есть два довольно очевидных способа нарисовать это: один с HEAD, указывающим на имя ветви, а затем с именем ветви, указывающим на коммиты:

                      HEAD
                       |
                       v
... <-F <-G <-H   <--master

Это в некоторых отношениях более точно, но не оченькомпактный.Для компактности я люблю опускать стрелки внутри самих коммитов.Они никогда не могут измениться (в отличие от стрелок с названиями веток) - ничто в любой коммит не может измениться.Поэтому, если мы видим:

...--F--G--H

, мы знаем, что H указывает на G, G указывает на F и так далее.Тогда у меня есть стрелка, идущая от master, чтобы найти H:

...--F--G--H   <-- master

и к этому я прикрепляю слово HEAD, чтобы сказать, что это текущая ветвь , так что если у нас есть больше ветвей, мы можем видеть, что происходит:

...--F--G--H   <-- master (HEAD)
         \
          I--J   <-- develop

Здесь у нас есть две ветви;имя develop указывает на коммит J, чей родитель I, что ведет к G и F и т. д., в то время как имя master указывает на H, что приводит кG и F и т. Д.

Кроме того: какая ветвь (-и) является коммитом "on"?

Если мы посмотрим на вышесказанное, мы можем сказать, что коммит H включен master и J включен develop.Это довольно естественно, поскольку эти имена указывают непосредственно на эти коммиты.Но как насчет коммита G, на какой ветке или ветвях он находится?

Некоторые системы выбирают один ответ и придерживаются его.Git отличается.Git говорит, что G находится на каждой ветви, которая может добраться до G, поэтому она на и master и develop.Чтобы добраться до G с master, мы возвращаемся на один прыжок.Чтобы добраться до G с develop, вернемся на два прыжка.В любом случае, мы приземлимся на G.

git log и git rev-list, просто следуя этим стрелкам

Учитывая некоторую отправную точку, такую ​​как master или develop или даже HEAD, что git log делает, говоря проще:

  • Показать коммит, который он имеет прямо сейчас, что бы это ни было.
  • Переход к родительскому коммиту.
  • Повторяйте, пока у нас не закончится фиксация.

Это описание не неверно , но в нем отсутствует много важных деталей.Первое осложнение возникает при слияниях.Давайте возьмем наш пока что график и объединяем develop обратно в master, используя:

$ git checkout master
$ git merge develop

Не вдаваясь в , как работает git merge- это отдельный вопрос и ответ (но он уже задавался много раз) - в итоге мы получим следующий график:

...--F--G--H---K   <-- master (HEAD)
         \    /
          I--J   <-- develop

Commit K - это merge commit , что означает егоимеет по крайней мере двух родителей.Два родителя K: H (как обычно), а также J (потому что мы объединили коммит J, найденный через имя develop).

После git log показываетcommit K, на какой коммит он должен перейти?Это может выбрать любой из них.Что он действительно делает, так это помещает оба в очередь, затем выбирает один и показывает его, а затем помещает его родителя в очередь, если он этого еще не сделал.Затем он выбирает еще один из очереди и повторяет:

  • Первоначально поместите коммиты, перечисленные в командной строке, в очередь.Если вы не указали какие-либо конкретные коммиты, git log использует HEAD.Затем в цикле:
    • Показать коммит, находящийся в начале очереди.
    • Если родители коммита еще не поставлены в очередь и еще не были показаны, поместите их все вочередь.
  • Повторять цикл до тех пор, пока очередь не станет пустой (или пользователь не выйдет).

Поскольку есть очередь, есть какое-то волшебство, чтобы управлять тем, кто на фронте .По умолчанию это выполняется с помощью сортировки по дате / отметке времени, но вы можете изменить это с помощью различных параметров сортировки.

Это означает, что Git по умолчанию сначала будет git log, show commit K, затем один из H или J, затем один из H или I, затем другой из H или I, и теперь очередь содержит только G, поэтому порядок ясен (G, затем F).Обратите внимание, что Git не может добраться до I, не пройдя J, поэтому J определенно выйдет раньше, чем I, но Git может добраться до H двумя способами, поэтому мы не знаем точно, гдеH выходит.

Ограничения на то, что ставится в очередь и / или показывается

Независимо от того, что вы делаете, git log и git rev-list всегда должныпройти через эту приоритетную очередь, выбрать следующий коммит, который нужно показать, добавить родительские коммиты в очередь и выполнить цикл.Но вы можете контролировать , какие родители добавляются и / или , какие коммиты действительно отображаются .

, какие родители ручки управления:

  • --first-parent: это говорит о том, что когда ходовой код попадает в коммит слияния, он должен добавить только первый родительский объект этого слияния.В нашем примере коммит слияния K имеет двух родителей, H является первым, поэтому с --first-parent, git log происходит переход с K до H до G, игнорируя коммиты, которые мы слили сбоковая ветвь.

  • --no-walk: это говорит о том, что прогулочный код ничего не должен делать: никогда не добавлять родителей.Это делает цикл довольно быстрым: мы видим только коммиты, перечисленные в командной строке.

, который показывает ручки , гораздо сложнее, так каких очень много.Здесь я собираюсь игнорировать все ориентированные на pathspec и смотреть только на --author и --committer, а также на --max-count / -n число.Первые два сообщают Git: Показать коммит, только если в списке указан автор или коммиттер. (Вы можете перечислить более одного --author или --committer; Git покажет коммит, если он соответствует любомуиз указанных вами имен.)

Обратите внимание, что walk по-прежнему основан на графике.Просто вы не видите коммиты, у которых нет нужного автора или коммиттера.

Между тем число --max-count aka -n сообщает Git, что он должен выйти изцикл после показывает некоторое количество коммитов.Например, при -n 5 --author automatic@local Git будет выполнять все коммиты как обычно, показывая, какие из них созданы automatic@local, но как только будет показано пять таких коммитов, остановитесь.Конечно, он остановится рано, если будет меньше коммитов.

Когда использовать git log против git rev-list

Команда git log - это то, что Git называет фарфор: все должно быть чистым, блестящим и привлекательным для пользователей.Таким образом, это то, что пользователи могут настроить.Вы можете установить цвета вывода, такие параметры, как log.decorate и другие полезные (для человека) элементы.

Команда git rev-list гораздо более строгая и скучная.Это то, что Git называет слесарным делом: программа, предназначенная для получения результатов, которые не обязательно хороши для людей, но полезны для других компьютерных программ .Он ведет себя одинаково, независимо от того, кто запускает , поэтому программа, которой требуется некоторая информация, которую может предоставить git rev-list, может получить ее согласованным образом.(Если хотите, эта программа может быть все более причудливой и ориентированной на человека.) То, что git rev-list производит по умолчанию, представляет собой просто последовательность хэшей коммитов, которые представляют собой идентификаторы хешей коммитов, которые одинаковы *Команда 1381 * показала бы.

По какой-то причине git log начнется с HEAD по умолчанию, а git rev-list - нет.Итак, чтобы преобразовать команду git log (которую вы тестируете, чтобы убедиться, что получаете правильные коммиты) в git rev-list (которую вы будете использовать в какой-то другой программе), вам иногда нужно добавить HEADк аргументам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...