Используя Git, покажите все коммиты, которые существуют * только * в одной конкретной ветке, а не * любые * другие

86

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

Это немного другое. Я хотел бы узнать , какие коммиты находятся на одной ветви , а не на каких - либо других отраслях.

Вариант использования - стратегия ветвления, при которой некоторые ветки следует только объединять, а не фиксировать напрямую. Это будет использоваться, чтобы проверить, были ли сделаны какие-либо коммиты непосредственно в ветке, предназначенной только для слияния.

РЕДАКТИРОВАТЬ: Ниже приведены шаги по настройке фиктивного репозитория git для тестирования:

git init
echo foo1 >> foo.txt
git add foo.txt
git commit -am "initial valid commit"
git checkout -b merge-only
echo bar >> bar.txt
git add bar.txt
git commit -am "bad commit directly on merge-only"
git checkout master
echo foo2 >> foo.txt 
git commit -am "2nd valid commit on master"
git checkout merge-only 
git merge master

Должна появиться только фиксация с сообщением «плохая фиксация непосредственно при только слиянии», которая была сделана непосредственно в ветке только слияния.

Джиммёрр
источник
1
В этом вопросе предполагается, что все объединенные ветки в настоящее время доступны в репо, никогда не удаляются после полного слияния и, возможно, никогда не объединяются с перемоткой вперед. Дайте мне знать, если я чего-то упускаю, но мне кажется, что это работает только для относительно небольшого набора разрешенных веток слияния из, так почему бы просто не использовать git log ^branch1 ^branch2 merge-only-branchсинтаксис?
Карл Билефельдт
1
git log ^branch1 ^branch2 merge-only-branchТребует перечислений каждой отдельной ветви. Этого можно избежать с помощью умного использования bash / grep (см. Мой ответ ниже), но я надеюсь, что в git есть встроенная поддержка для этого. Вы правы, предполагая, что все ветки слияния являются удаленными (только локальные так же хороши, как и несуществующие для других разработчиков). Использование --no-mergesисключает любые коммиты, которые были объединены, а затем была удалена их исходная ветвь слияния из, поэтому предполагается, что ветки слияния из ветки сохраняются до тех пор, пока они не будут объединены в ветвь без слияния (т.е.
jimmyorr

Ответы:

75

Мы только что нашли это элегантное решение

git log --first-parent --no-merges

В вашем примере, конечно, все еще отображается первоначальная фиксация.

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

wrtsprt
источник
1
Просто, эффективно, лучше.
Забба
1
Поскольку первоначальная фиксация на мастере все еще отображается, это не отвечает на вопрос.
jimmyorr 06
6
Это само по себе не удовлетворяет «фиксаций , которые существуют только в этой отрасли» Состояние- его показывает initial valid commit, что часть обоих merge-onlyи masterветвей. Однако, если кто-то приложит усилия, чтобы поместить в конец имя текущей ветки, за которым следуют имена ветвей с префиксом ^, которые, как известно, исходят из текущей ветки, это решит половину проблем (за исключением вещей, которые были объединены). Пример:git log --first-parent --no-merges merge-only ^master
Слипп Д. Томпсон
13
Я не уверен, почему за это так много голосов, это вообще не имеет отношения к вопросу. Это определенно не дает той информации, которую искал плакат.
Chris Rasys
2
Этот ответ может быть не идеальным. Но это просто и, безусловно, в некоторой степени работает. Я считаю полезным добавить имя ветки - т.е. отфильтровать, что все коммиты принадлежат данной ветке:git log --first-parent --no-merges | grep <branch_name>
artm
29

Предоставлено моим дорогим другом Редмумба :

git log --no-merges origin/merge-only \
    --not $(git for-each-ref --format="%(refname)" refs/remotes/origin |
    grep -Fv refs/remotes/origin/merge-only)

... где origin/merge-onlyнаходится имя вашей удаленной ветки только для слияния. При работе на локальном-только мерзавца репо, заменитель refs/remotes/originс refs/heads, и заменить имя удаленного филиала origin/merge-onlyс именем локального филиала merge-only, а именно:

git log --no-merges merge-only \
    --not $(git for-each-ref --format="%(refname)" refs/heads |
    grep -Fv refs/heads/merge-only)
Джиммёрр
источник
2
Я надеюсь, что кто-то другой сможет предоставить решение без grep, используя только git, но если нет, это выглядит довольно элегантно.
jimmyorr
1
Да, элегантно. Используйте git for-each-refдля перечисления каждого имени ссылки в источнике и grep -vдля исключения ветки только слияния. git logпринимает --notпараметр, которому мы передаем наш список всех ссылок (кроме ветки только слияния). Если у вас есть более элегантный ответ на проблему, давайте его послушаем.
jimmyorr
2
О, я уверен, что это самый элегантный ответ. Я только утверждаю, что это немного "многословно / сложно" для истинной элегантности. :-) Не хотел умалить ваш подход, сэр!
Крис К.
1
Трейлинг /*в git for-each-refsкомандах не опирается на соответствие некоторых существующий файла и не имеющий failglobили nullglobмножество ( Баш вариантов, другие оболочки изменяются). Вы должны либо заключить в кавычки / избежать звездочек, либо просто оставить завершение /*( git for-each-refшаблоны могут соответствовать «от начала до косой черты»). Возможно, используйте grep -Fv refs/remotes/origin/foo( refs/heads/foo), чтобы более строго определить, какие ссылки удаляются.
Крис Джонсен,
3
Это можно упростить, если вы просто хотите видеть коммиты в одной ветке, а не в другой:, git log --no-merges B1 --not B2где B1 - это ветка, которая вас интересует, а B2 - ветка, с которой вы хотите сравнить B1. И B1, и B2 могут быть локальными или удаленными ветвями, поэтому вы можете указать git log --no-merges master --not origin/masterили даже указать две удаленные ветки.
mr.b
21
git log origin/dev..HEAD

Это покажет вам все коммиты, сделанные в вашей ветке.

Пракаш
источник
2
@Prakash origin/branchNameбудет указывать на заголовок удаленной ветки И HEADуказывать на commitid последней локальной фиксации в этой ветке. Так что это не сработает, если вы использовали git push.
Bharat
Вы можете использовать это для сравнения другой локальной ветки. Флаг --no-merges также может быть удобен для ответа на исходный вопрос OP.
Пол Уипп,
15

@Prakash ответ работает. Просто для ясности ...

git checkout feature-branch
git log master..HEAD

перечисляет коммиты в функциональной ветке, но не в восходящей ветке (обычно это ваш главный).

Брайан
источник
12

Может быть, это может помочь:

git show-branch

грзуй
источник
2
Хотя теоретически это может дать ответ на вопрос, было бы предпочтительнее включить сюда основные части ответа и предоставить ссылку для справки.
Владимир Пантелеев
На самом деле это очень полезно. См. Stackoverflow.com/a/7623339/874188 для более подробного примера и некоторых связанных ответов.
Tripleee
7

Попробуй это:

git rev-list --all --not $(git rev-list --all ^branch)

В основном git rev-list --all ^branchполучает все ревизии не в ветке, а затем вы все ревизии в репо и вычитаете предыдущий список, который является ревизиями только в ветке.

После комментариев @Brian:

Из документации git rev-list:

List commits that are reachable by following the parent links from the given commit(s)

Таким образом, такая команда, как git rev-list Aгде A - это фиксация, будет перечислять коммиты, доступные из A, включая A.

Имея это в виду, что-то вроде

git rev-list --all ^A

перечислит коммиты, недоступные из A

Таким образом, git rev-list --all ^branchбудут перечислены все коммиты, недоступные из конца ветки. Что удалит все коммиты в ветке, или, другими словами, коммиты, которые есть только в других ветках.

Теперь перейдем к git rev-list --all --not $(git rev-list --all ^branch)

Это будет похоже git rev-list --all --not {commits only in other branches}

Итак, мы хотим перечислить, allчто недоступно изall commits only in other branches

Это набор коммитов, которые есть только в ветке. Возьмем простой пример:

             master

             |

A------------B

  \

   \

    C--------D--------E

                      |

                      branch

Здесь цель - получить D и E, коммитов нет ни в какой другой ветке.

git rev-list --all ^branch дать только B

Теперь git rev-list --all --not Bэто то , к чему мы подошли. Что также git rev-list -all ^B- мы хотим, чтобы все коммиты были недоступны из B. В нашем случае это D и E. Это то, что мы хотим.

Надеюсь, это объясняет, как команда работает правильно.

Изменить после комментария:

git init
echo foo1 >> foo.txt
git add foo.txt
git commit -am "initial valid commit"
git checkout -b merge-only
echo bar >> bar.txt
git add bar.txt
git commit -am "bad commit directly on merge-only"
git checkout master
echo foo2 >> foo.txt 
git commit -am "2nd valid commit on master"

После вышеуказанных шагов, если вы сделаете a, git rev-list --all --not $(git rev-list --all ^merge-only)вы получите коммит, который искали - "bad commit directly on merge-only"тот.

Но как только вы сделаете последний шаг в своих шагах, git merge masterкоманда не даст ожидаемого результата. Потому что на данный момент нет фиксации, которой не было бы в режиме только слияния, поскольку одна дополнительная фиксация в мастере также была объединена в режим только слияния. Так git rev-list --all ^branchдает пустой результат и, следовательно git rev-list -all --not $(git rev-list --all ^branch), все коммиты будут доступны только для слияния.

Manojlds
источник
1
Хм ... не знаю почему, но это не совсем работает. Передача вывода вашей команды по конвейеру для xargs -L 1 -t git branch -a --containsотображения множества ложных срабатываний (коммитов, которые фактически находятся в других ветвях). Пробовал с и без --no-merges. Спасибо за ответ!
jimmyorr
Кажется, у меня все работает нормально, насколько я могу видеть в фиктивном репозитории git.
manojlds
Я добавил шаги по созданию фиктивного репозитория git, чтобы продемонстрировать проблему с вашим ответом.
jimmyorr
Ах, упс. Проголосовал за это, прежде чем я обдумал это полностью. git rev-list --all ^branchпредоставит вам все коммиты, которых нет branch. Затем вы вычитаете это из списка, который находится в branch; но по определению все коммиты, которых нет, не branchвходят branch, поэтому вы ничего не вычитаете. Джиммёрр ищет коммиты, которые находятся, branchно не находятся в masterлюбой другой ветке. Вы не хотите вычитать коммиты, которых нет branch; вы хотите вычесть коммиты из любых других веток.
Брайан Кэмпбелл,
1
@manojlds "(все ревизии) - (все ревизии не в ветке) = ревизия в ветке." Да, это работает, чтобы внести все изменения branch, но так же работает git rev-list branch. Вы просто пишете git rev-list branchболее сложным (и медленным) способом. Не получается ответить на вопрос, как найти все коммиты branch , которых нет ни в одной другой ветке .
Брайан Кэмпбелл,
2

Другой вариант принятых ответов для использования с master

git log origin/master --not $(git branch -a | grep -Fv master)

Отфильтруйте все коммиты, которые происходят в любой ветке, кроме master.

Хайме Хорхе
источник
0

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

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

...--F--G--H   <-- master
         \
          I--J   <-- develop

где прописные буквы обозначают фактические идентификаторы хэша Git, мы часто ищем только фиксациюH или только фиксацииI-J в нашем git logвыводе. Сквозные коммиты Gнаходятся в обеих ветвях, поэтому мы хотели бы их исключить.

(Обратите внимание, что на графиках, нарисованных таким образом, более новые коммиты расположены справа. Имена выбирают единственную крайнюю правую фиксацию в этой строке. Каждая из этих фиксаций имеет родительскую фиксацию, которая является фиксацией слева от них: родительский элемент H- G, и родительJ является Iродитель. Iэто Gснова родитель. Gэто Fи Fесть родитель , который просто не показан здесь: это часть ...раздела).

В этом особенно простом случае мы можем использовать:

git log master..develop    # note: two dots

для просмотра I-Jили:

git log develop..master    # note: two dots

Hтолько для просмотра . Имя справа после двух точек говорит Git: да, эти коммиты . Имя слева перед двумя точками говорит Git: нет, не эти коммиты . Git начинается с конца - при фиксации Hили фиксацииJ - и работает в обратном направлении . Для (гораздо) более подробной информации см. Think Like (a) Git .

Исходный вопрос сформулирован так: желание состоит в том, чтобы найти коммиты, которые доступны по одному конкретному имени, но не по любому другому имени в той же общей категории. То есть, если у нас более сложный график:

               O--P   <-- name5
              /
             N   <-- name4
            /
...--F--G--H--I---M   <-- name1
         \       /
          J-----K   <-- name2
           \
            L   <-- name3

мы могли бы выбрать одно из этих имен, например name4или name3, и спросить: какие коммиты можно найти по этому имени, но не по другим именам? Если мы выберем name3ответ - совершить L. Если мы выберемname4 , то ответ - никаких коммитов: коммит, который name4называет коммитом, Nно коммит, Nможно найти, начав с него name5и работая в обратном направлении.

Принятый ответ работает с именами удаленного отслеживания, а не с именами ветвей, и позволяет вам назначить одно - написанное по буквам origin/merge-only- как выбранное имя и просмотреть все другие имена в этом пространстве имен. Он также избегает показа слияний: если мы выберем name1«интересное имя» и скажем, покажи мне коммиты, которые доступны изname1 но не по любому другому имени , мы увидим коммит слияния, Mа также обычный коммит I.

Самый популярный ответ - совсем другой. Все дело в обходе графика фиксации, не следуя обеим сторонам слияния и не показывая каких-либо коммитов, которые являются слияниями. name1Например, если мы начнем с , мы не будем показывать M(это слияние), но если предположить, что первым родителем слияния Mявляется фиксация I, мы даже не будем смотреть на коммиты Jи K. Мы в конечном итоге показывая фиксации I, а также совершает H, G, Fи так далее никто из них слияния коммитов , и все они достижимы, начинаясьM и работать в обратном направлении, посещая только первый родитель каждого слияния совершить.

Самый популярный ответ довольно хорошо подходит, например, для того, чтобы посмотреть, masterкогда masterпредполагается использовать ветвь только для слияния. Если вся «настоящая работа» была проделана над боковыми ветвями, которые впоследствии были объединены master, у нас будет такая картина:

I---------M---------N   <-- master
 \       / \       /
  o--o--o   o--o--o

где все oкоммиты без буквенного имени являются обычными (без слияния) коммитами, а Mи Nявляются слиянием. Фиксация I- это начальная фиксация: самая первая когда-либо сделанная фиксация и единственная, которая должна быть на главном сервере, но не фиксация слияния. Если git log --first-parent --no-merges masterпоказан какой-либо коммит, отличный от I , у нас будет такая ситуация:

I---------M----*----N   <-- master
 \       / \       /
  o--o--o   o--o--o

где мы хотим видеть фиксацию, *которая была сделана непосредственно master, а не путем слияния какой-либо ветки функции.

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

Имена для удаленного отслеживания вроде origin/master названия веток ?

Некоторые части Git говорят, что это не так:

git checkout master
...
git status

говорит on branch master, но:

git checkout origin/master
...
git status

говорит HEAD detached at origin/master . Я предпочитаю согласиться с тем, что git checkout/ git switch: origin/masterне является названием ветки, потому что вы не можете «войти» в него.

В принятом ответе вorigin/* качестве «имен веток» используются имена удаленного отслеживания :

git log --no-merges origin/merge-only \
    --not $(git for-each-ref --format="%(refname)" refs/remotes/origin |
    grep -Fv refs/remotes/origin/merge-only)

Средняя строка, которая вызывает git for-each-ref, перебирает имена удаленного отслеживания для указанного удаленного объекта origin.

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

git log пересекает некоторую часть (части) графа фиксации

На самом деле мы ищем здесь серию так называемых даглетов: см. Что именно мы подразумеваем под «ветвью»? То есть мы ищем фрагменты в некотором подмножестве общего графа фиксации. .

Всякий раз, когда у нас есть Git, смотрим на имя ветки, например master, имя тега, напримерv2.1 или на имя удаленного отслеживания, как origin/masterправило, мы хотим, чтобы Git сообщал нам об этом коммите и каждом коммите, к которому мы можем перейти из этого коммита: начиная с этого , и работая в обратном направлении.

В математике это называется ходьбой по графику . Граф фиксации Git - это направленный ациклический граф или DAG , и этот вид графа особенно подходит для прогулок. Обходя такой граф, можно посетить каждую вершину графа, достижимую по используемому пути. Вершины в графе Git - это коммиты, а ребра - это дуги - односторонние ссылки, идущие от каждого дочернего элемента к каждому родительскому элементу. (Здесь Think Like (а) Git приходит . Односторонняя природа дуг означает, что Git должен работать в обратном направлении, от дочернего к родительскому.)

Две основные команды Git для обхода графов: git logи git rev-list. Эти команды очень похожи - на самом деле, они в основном построены из одних и тех же исходных файлов, - но их вывод отличается: git logвывод для чтения людьми, а git rev-listвывод, предназначенный для чтения другими программами Git. 1 Обе команды выполняют такой вид обхода графа.

Обход графа, который они делают, специфичен: с учетом некоторого набора коммитов отправной точки (возможно, только одного коммита, возможно, группы хэш-идентификаторов, возможно, группы имен, которые разрешаются в хеш-идентификаторы), обход графа, посещение коммитов . Конкретные директивы, такие как --notили префикс ^, или --ancestry-path, или --first-parent, каким-то образом модифицируют обход графа .

Во время обхода графа они посещают каждую фиксацию. Но они печатают только некоторое выбранное подмножество пройденных коммитов. Директивы, такие как --no-mergesили--before <date> сообщают коду обхода графа, который выполняет печать .

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

git log master

превращает имя masterв необработанный идентификатор хеша и помещает этот идентификатор в очередь. Или:

git log master develop

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

Приоритет коммитов в этой очереди определяется еще большим количеством аргументов. Например, аргумент --author-date-orderуказывает git logили git rev-listиспользовать метку времени автора , а не метку времени коммиттера. По умолчанию используется временная метка коммиттера и выбирается самая последняя по дате фиксация: та, которая имеет наибольшую числовую дату. Итак, при master developусловии, что они разрешены для двух разных коммитов, Git покажет, какой из них позже первым, потому что он будет в начале очереди.

В любом случае код обхода ревизий теперь выполняется в цикле:

  • Пока в очереди есть коммиты:
    • Удалите первую запись в очереди.
    • Решите, печатать ли вообще этот коммит. Например --no-merges: ничего не печатать, если это фиксация слияния; --before: ничего не печатать, если его дата не раньше назначенного времени. Если печать не подавлена, распечатайте фиксацию: дляgit log , покажите ее журнал; для git rev-list, напечатайте его хэш-идентификатор.
    • Поместите некоторые или все родительские коммиты этого коммита в очередь (до тех пор, пока их там нет и они еще не были посещены 2 ). Обычно по умолчанию помещаются все родители. Использование --first-parentподавляет все, кроме первого родителя каждого слияния.

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

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

Когда происходит слияние, и мы следуем за обоими родителями - обеими «ногами» слияния - или когда вы отдаете git logилиgit rev-list более одного стартового коммита, параметры сортировки имеют значение.

Наконец, рассмотрите эффект спецификатора фиксации --notили ^перед ним. Их можно записать несколькими способами:

git log master --not develop

или:

git log ^develop master

или:

git log develop..master

все означают одно и то же. Это --notпохоже на префикс, ^за исключением того, что он применяется к более чем одному имени:

git log ^branch1 ^branch2 branch3

означает не ветка1, не ветка2, да ветка3; но:

git log --not branch1 branch2 branch3

означает не ветвь1, не ветка2, не ветка3, и вы должны использовать секунду, --notчтобы отключить ее:

git log --not branch1 branch2 --not branch3

что немного неудобно. Две директивы not объединяются с помощью XOR, поэтому, если вы действительно хотите, вы можете написать:

git log --not branch1 branch2 ^branch3

иметь в виде , не branch1, а не branch2, да branch3 , если вы хотите Затемнение .

Все они работают, влияя на обход графа. В качествеgit log и git rev-listходит граф, он убеждается не ставить в приоритет очереди любой коммит , который доступен из любого из отрицаний ссылок. (Фактически, они также влияют на начальную настройку: отрицаемые коммиты не могут попасть в приоритетную очередь прямо из командной строки, поэтому git log master ^master, например, ничего не показывает.)

Это используется во всем причудливом синтаксисе, описанном в документации gitrevisions , и вы можете раскрыть это с помощью простого вызова git rev-parse. Например:

$ git rev-parse origin/pu...origin/master     # note: three dots
b34789c0b0d3b137f0bb516b417bd8d75e0cb306
fc307aa3771ece59e174157510c6db6f0d4b40ec
^b34789c0b0d3b137f0bb516b417bd8d75e0cb306

Трехточечный синтаксис означает коммиты достижимы с левой или правой стороны, но исключают коммиты, доступные с обеих сторон . В этом случае origin/masterфиксация b34789c0b,, сама доступна из origin/pu( fc307aa37...), поэтому origin/masterхэш появляется дважды, один раз с отрицанием, но на самом деле Git достигает синтаксиса из трех точек, помещая две положительные ссылки - два неотрицательных идентификатора хэша - и один отрицательный, представленный ^префиксом.

Аналогично:

$ git rev-parse master^^@
2c42fb76531f4565b5434e46102e6d85a0861738
2f0a093dd640e0dad0b261dae2427f2541b5426c

В ^@синтаксических средств все родители данного обязательство , и master^сам-первый родитель коммит выбрано ответвление имя master-эт слияние фиксацию, поэтому он имеет два родителей. Это двое родителей. А также:

$ git rev-parse master^^!
0b07eecf6ed9334f09d6624732a4af2da03e38eb
^2c42fb76531f4565b5434e46102e6d85a0861738
^2f0a093dd640e0dad0b261dae2427f2541b5426c

^!Суффикс означает само обязательство, но ни один из его родителей . В данном случае master^это 0b07eecf6.... Мы уже видели обоих родителей с ^@суффиксом; вот они снова, но на этот раз отрицаемые.


1 Многие программы Git буквально запускаются git rev-listс различными параметрами и читают их вывод, чтобы узнать, какие коммиты и / или другие объекты Git использовать.

2 Поскольку граф является ациклическим , можно гарантировать, что ни один из них еще не был посещен, если мы добавим ограничение никогда не показывать родительский элемент, прежде чем показывать всем его дочерним элементам приоритет. --date-order, --author-date-orderИ --topo-orderдобавить это ограничение. Порядок сортировки по умолчанию, у которого нет имени, не имеет. Если временные метки фиксации ошибочны - если, например, некоторые фиксации были сделаны «в будущем» компьютером с отключенными часами, - это в некоторых случаях может привести к странному виду вывода.


Если вы зашли так далеко, теперь вы много знаете о git log

Резюме:

  • git log показывает некоторые выбранные коммиты при прохождении некоторой или всей части графика.
  • --no-mergesАргумент, найденный в обоих принятых и в настоящее время, топ-рейтинг ответов, подавляет показывая некоторые коммиты , которые являются шли.
  • --first-parentАргумент, с текущей-топ-рейтинг-ответ, подавляет ходьбе некоторые части графика, в течение граф-ходить сам.
  • --notПрефикс аргументов командной строки, используемый в общепринятом ответ, подавляет когда - либо посещать некоторые части графика вообще с самого начала.

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

торек
источник