Поиск в git log по хешу коммита - PullRequest
0 голосов
/ 12 марта 2019

У меня есть мерзавец несколько месяцев назад (скажем, xyz), и я хотел бы просмотреть все коммиты в ветке master до и после этого хэша до сегодняшнего дня.

Я знаю, git checkout xyz~1 возвращает 1 коммит до этого хэша, а git log показывает все предыдущие коммиты, но я не знаю, как двигаться дальше?

Можно ли в этом случае использовать --grep функцию git?

Ответы [ 3 ]

1 голос
/ 12 марта 2019

Рассмотрим следующую картину:

              I  <-J
             /
... <-G  <-H
             \
              K  <-L

Вышеприведенное представляет коммиты Git - H обозначает какой-то большой некрасивый хеш-идентификатор, как и G, I и так далее. (Примечание: строки от K до H и от I до H должны указывать влево / назад, как и другие, но у меня нет хороших символов со стрелками, которые работают в любой системе, и Я рисую это с текстом вместо графики.)

Причина, по которой вы можете легко вернуться назад, заключается в том, что коммит H содержит большой уродливый идентификатор хеша коммита G. Мы говорим, что H указывает на G. Поэтому, если вы стоите на H и запускаете git log, Git показывает вам H, затем G, затем все, что предшествует G (вероятно, F), и т. Д.

Вы хотите пойти другим путем. Но ... в каком направлении это это? Есть два пути вперед, ни один из которых Git не сможет легко найти для вас. Один идет к I, а затем J. Другой идет к K, а затем L.

То, что вы можете сделать, это выбрать более позднюю начальную точку - конечную точку? Git может сделать это легко благодаря встроенным стрелкам, направленным назад от каждого коммита.

Когда у вас Git работает в обратном направлении, Git, в конце концов, придет к какому-то коммиту, чей родитель H. Это «прямой» коммит в направлении конечной точки, которую вы выбрали . Конечно, это не другой форвардный коммит.

Основная проблема здесь заключается в том, что может быть много конечных точек, из которых только несколько, если таковые имеются, ведут к H:

...--G--H--o   <-- master
      \
       J--o--o   <-- develop
           \
            o--o   <-- feature

Мы называем эти конечные точки ветви , или, точнее, имена ветвей . Имя указывает на коммит tip . Каждый коммит слева - независимо от того, в какой строке он находится - находится в этой ветви, что означает, что на этом графике коммит G находится в каждой ветви. Коммит J включен и develop и feature.

Выберите название ветви, которое, по вашему мнению, в конечном итоге приведет вас туда, где вы сейчас находитесь. Затем попросите Git сделать:

git log --topo-order --ancestry-path HEAD..master
Например,

, чтобы Git начинался с master и работал в обратном направлении. (HEAD - это коммит, на котором вы стоите сейчас, на этой карте коммитов и их соединений. Это большая красная точка «вы здесь», и она автоматически перемещается вместе с вами по мере вашего движения о.)

Последовательный последний коммит будет получен сразу после вашего текущего коммита, , если ваш текущий коммит будет достигнут с верхушкой master. Если нет, то последним коммитом, который получается из этого, является некоторый коммит, достижимый из master, который не находится в той же ветви (ветвях), которые содержат HEAD. Например, git log --ancestry-path HEAD..feature будет перечислять коммиты, начиная с одного feature пункта, и работая обратно, пока не достигнет J. С J, git log вернется к G. Это не HEAD / H, но достижимо с H, поэтому на этом остановится git log. Это не коммит после H.

Это означает, что если вы не знаете наверняка, какие ветви содержат H, вы не будете знать, с чего начать. Так что используйте:

git branch --contains HEAD

, чтобы получить список имен веток, который, когда Git запускает их и работает в обратном направлении, эти ветки содержат commit H / HEAD. Затем вы можете использовать трюк --ancestry-path, чтобы идти «вперед» в этом направлении (вы все еще действительно идете назад, вы просто останавливаете как раз перед тем, как вы доберетесь до H).

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

          I--J
         /    \
...--o--H      M--N   <-- branch
         \    /
          K--L

Moving «вперед» с H до N, вы либо идете I-J-M-N, либо K-L-M-N. В любом случае вы можете забыть посетить два, которые вы пропустили. Так что будьте осторожны с этим.

Использование git rev-list

Зачастую вы не хотите просматривать весь вывод git log здесь. Есть несколько коротких путей, но помните, если / когда вы используете их, вы можете потерять на внутренних структурах ветвления и слияния, таких как кольцо, нарисованное выше. В любом случае, git rev-list делает то же самое, что и git log, за исключением того, что он просто печатает хэш-идентификаторы. Используя --topo-order --reverse | head -1, вы можете напечатать список в обратном направлении, а затем удалить все, кроме первого; или используйте его без --reverse и | tail -1 для того же эффекта. Вы также можете опустить имя HEAD. Итак:

git checkout $(git rev-list --ancestry-path --topo-order ..branch | tail -1)

переместит вашу отдельную ГОЛОВКУ на один шаг в направлении к branch, если такой шаг есть.

0 голосов
/ 12 марта 2019
  1. для просмотра коммитов "до xyz", просто используйте:

    git log xyz
    
  2. для просмотра коммитов "в мастере, которые произошли после xyz ", технически вы можете использовать:

    git log xyz..master
    

, вторая команда исключит xyz из списка, в зависимости от ваших конкретных потребностей, вы можете использовать xyz~1 вместо xyz:

git log xyz~1..master

git log также имеет массу опций для форматирования своего вывода.

Один полезный набор опций для просмотра большого набора коммитов:

git log --oneline --graph xyz
git log --oneline --graph xyz..master
0 голосов
/ 12 марта 2019

Сложно дать однократный ответ, потому что это зависит от того, как выглядит ваше дерево, где находится xyz и от того, как совершаются или объединяются коммиты с master .В этом ответе предполагается, что вас интересуют только коммиты от xyz , ведущие к master .

Скажите, что у нас есть это дерево:

*   f10abeb (HEAD -> master) Merge branch 'develop' into 'master'
|\  
| *   3a7ed63 Merge branch 'feature/A' into 'develop'
| |\  
| * | f3972b9 Update in develop 1
| | * f695720 Update in feature/A
| * | 20323a1 Update in develop 2 
| * | 3e81e7a Update in develop 3 
| * | 1e76a6c Update in develop 4
| * | d3bf88f Update in develop 5
| | * 205fc0e Update in feature/A

Скажитевы хотите получить журналы только между 2 коммитами до 20323a1 (xyz) и вашей локальной копией master (что, я полагаю, вы подразумеваете под " до сегодняшнего дня ").Вам не нужны «внутренние» коммиты в feature/A, но вы хотите увидеть, когда они были объединены.(Я предполагаю, что здесь довольно много).

Во-первых, вам нужно оформить 2 коммита до 20323a1:

git checkout 20323a1~2

Это приведет вас к 1e76a6c.
Затем вы можете сделать:

git log --ancestry-path @^..master

Это даст вам журналы для:
(я удалил некоторую информацию, такую ​​как дата и время и т. Д.)

commit f10abebbfa9bce8074e9a4854af4fc1a000b2f6a
Merge: 6011c88 3a7ed63

    Merge branch 'develop' into 'master'

commit 3a7ed6334d492ebb7960c97c1c59c88d40c28108
Merge: f3972b9 f695720

    Merge branch 'feature/A' into 'develop'

commit f3972b9ca16ff27914120de12105b8203a2682fa

    Update in develop 1

commit 20323a1fc4c636b7e12650659ca049c2a1c497c4

    Update in develop 2 

commit 3e81e7a1624e6914dc152ca315c727e15ebf3300

    Update in develop 3

commit 1e76a6cb326ffce64ff22480a71b49de4dbdff73

    Update in develop 4

* 1035Параметр *--ancestry-path будет « отображать только те коммиты, которые существуют непосредственно в цепочке предков между commit1 и commit2 » (в данном примере текущий коммит и master).

r1..r2 - это запись в точечном диапазоне, означающая коммиты " коммиты, которые достижимы из r2, исключая те, которые достижимы из r1 ".Затем мы указываем r1 как текущий коммит (@) и r2 как master.

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