TL; DR; как упоминается в GitMerge 2019:
git config --global core.commitGraph true
git config --global gc.writeCommitGraph true
cd /path/to/repo
git commit-graph write
На самом деле (см. В конце) первые две конфигурации не нужны с Git 2.24+ (3 квартал 2019 г.): по умолчанию они true
.
Как упоминается в T4cC0re в комментарии:
Если вы используете git версии 2.29 или выше, вам лучше запустить:
git commit-graph write --reachable --changed-paths
Это предварительно вычислит пути к файлам, так что git log
команды, привязанные к файлам, также выиграют от этого кеша.
Git 2.18 (второй квартал 2018 г.) улучшит git log
производительность:
См. commit 902f5a2 (24 марта 2018 г.) от Рене Шарфе (rscharfe
).
См. совершить 0aaf05b, зафиксировать 3d475f 2018) от Деррика Столи (derrickstolee
).
См. commit 626fd98 (22 марта 2018 г.) от Брайан М. carlson (bk2204
).
(Объединено Junio C Hamano - gitster
- < / a> в commit 51f813c, 10 апреля 2018 г.)
sha1_name
: используйте bsearch_pack()
для сокращений
При вычислении длины аббревиатуры для идентификатора объекта по одному пакетному файлу метод find_abbrev_len_for_pack()
в настоящее время реализует двоичный поиск.
Это одна из нескольких реализаций.
Одна проблема с этой реализацией заключается в том, что он игнорирует таблицу разветвления в pack-index
.
Преобразуйте этот двоичный поиск, чтобы использовать существующий bsearch_pack()
метод, который правильно использует таблицу разветвления.
Благодаря использованию таблицы разветвления вычисление сокращений происходит немного быстрее, чем раньше.
Для полностью переупакованной копии репозитория Linux улучшены следующие команды git log:
* git log --oneline --parents --raw
Before: 59.2s
After: 56.9s
Rel %: -3.8%
* git log --oneline --parents
Before: 6.48s
After: 5.91s
Rel %: -8.9%
Тот же Git 2.18 добавляет график фиксации: предварительное вычисление и сохранение информации, необходимой для обхода предков, в отдельном файле для оптимизации обхода графа.
См. совершить 7547b95, коммит 3d5df01, 049d51a, совершить 177722b, совершить 4f2542b, совершить 1b70dfd, совершить 2a2e32b (10 апреля 2018 г.) и зафиксировать f237c8b, rel =" noreferrer " , совершить 4ce58ee, совершить ae30d7b, b84f767, зафиксировать cfe8321, совершить f2af9f5 (2 апреля 2018 г.) от Деррик Столи (derrickstolee
).
(Объединено пользователем Junio C Hamano - gitster
- в commit b10edb2, 8 мая 2018 г.)
commit
: интегрировать график фиксации с анализом фиксации
Научите Git проверять файл графика фиксации для предоставления содержимого фиксации структуры при вызове _ 19_.
Эта реализация удовлетворяет всем пост-условиям фиксации структуры, включая загрузку родителей, корневое дерево и дату фиксации.
Если core.commitGraph
равно false
, не проверяйте файлы графиков.
В тестовом скрипте t5318-commit-graph .sh, добавьте output-matching
условия для операций с графами только для чтения.
Загружая коммиты из графика вместо анализа буферов фиксации, мы экономим много времени на длительных обходах фиксации.
Вот некоторые результаты производительности для копии репозитория Linux, где «master» имеет 678 653 доступных коммитов и отстает от «origin/master
» на 59 929 коммитов.
| Command | Before | After | Rel % |
|----------------------------------|--------|--------|-------|
| log --oneline --topo-order -1000 | 8.31s | 0.94s | -88% |
| branch -vv | 1.02s | 0.14s | -86% |
| rev-list --all | 5.89s | 1.07s | -81% |
| rev-list --all --objects | 66.15s | 58.45s | -11% |
Чтобы узнать больше о графике фиксации, см. Как работает 'git log --graph
'?.
Тот же Git 2.18 (второй квартал 2018 г.) добавляет дерево отложенной загрузки.
Код был обучен использовать дублированную информацию, хранящуюся в файле диаграммы фиксации, чтобы узнать имя объекта дерева для фиксации, чтобы избежать открытия и анализа объекта фиксации, когда это имеет смысл.
См. фиксацию 279ffad (30 апреля 2018 г.) по СЕДЕР Габор (szeder
).
См. зафиксировать 7b8a21d, зафиксировать 2e27bd7, , commit 891435d (6 апреля 2018 г.) Деррик Столи (derrickstolee
) .
(Объединено Junio C Hamano - gitster
- i n совершить c89b6e1, 23 мая 2018 г.)
commit-graph
: деревья с отложенной загрузкой для коммитов
Файл графика фиксации обеспечивает быстрый доступ к данным фиксации, включая OID корневого дерева для каждой фиксации в графе. При выполнении глубокого обхода графа коммитов нам может не потребоваться загружать большую часть деревьев для этих коммитов.
Отложите загрузку объекта дерева для фиксации, загруженной из графа, до тех пор, пока она не будет запрошена через get_commit_tree()
.
Не выполняйте отложенную загрузку деревьев для коммитов не в графе, поскольку для этого требуется дублирующий синтаксический анализ и относительное улучшение производительности, когда деревья не нужны. небольшой.
В репозитории Linux тесты производительности выполнялись для следующей команды:
git log --graph --oneline -1000
Before: 0.92s
After: 0.66s
Rel %: -28.3%
Git 2.21 (первый квартал 2019 г.) добавляет свободный кеш.
См. фиксацию 8be88db (7 января 2019 г.) и совершить 4cea1ce, совершить d4e19e5, совершить 0000d65 (06 января 2019 г.) ) от Рене Шарфе (rscharfe
).
(объединено с помощью Junio C Hamano - gitster
- в commit eb8638a, 18 января 2019 г.)
object-store
: используйте по одному oid_array
на подкаталог для свободного кеширования
Кэш незакрепленных объектов заполняется по одному подкаталогу по мере необходимости.
Он хранится в oid_array
, который нужно пересматривать после каждой операции добавления.
Таким образом, при запросе широкого диапазона объектов частично заполненный массив необходимо пересортировать до 255 раз, что в 100 раз дольше, чем при однократной сортировке.
Используйте по одному oid_array
для каждого подкаталога.
Это гарантирует, что записи нужно будет отсортировать только один раз. Это также позволяет избежать восьми шагов двоичного поиска для каждого поиска в кэше в качестве небольшого бонуса.
Кэш используется для проверки коллизий для заполнителей журнала %h
, %t
и %p
, и мы можем увидеть, как изменение ускоряет их в репозитории с ca. 100 объектов в подкаталоге:
$ git count-objects
26733 objects, 68808 kilobytes
Test HEAD^ HEAD
--------------------------------------------------------------------
4205.1: log with %H 0.51(0.47+0.04) 0.51(0.49+0.02) +0.0%
4205.2: log with %h 0.84(0.82+0.02) 0.60(0.57+0.03) -28.6%
4205.3: log with %T 0.53(0.49+0.04) 0.52(0.48+0.03) -1.9%
4205.4: log with %t 0.84(0.80+0.04) 0.60(0.59+0.01) -28.6%
4205.5: log with %P 0.52(0.48+0.03) 0.51(0.50+0.01) -1.9%
4205.6: log with %p 0.85(0.78+0.06) 0.61(0.56+0.05) -28.2%
4205.7: log with %h-%h-%h 0.96(0.92+0.03) 0.69(0.64+0.04) -28.1%
Git 2.22 (апрель 2019 г.) проверяет ошибки перед использованием данных, считанных из файла графика фиксации.
См. commit 93b4405, совершить 43d3561, зафиксировать 945944 >, зафиксировать f6761fa (21 февраля 2019 г.), var Arnfjör Bjarmason (_42 _).
(Объединено Junio C Hamano - gitster
- в commit a5e4be2, 25 апреля 2019 г.)
commit-graph
напишите: не умирай, если существующий граф поврежден
Когда написано commit-graph
, мы вызываем parse_commit()
. Это, в свою очередь, вызовет код, который будет консультироваться с существующим commit-graph
о фиксации, если граф поврежден, мы умрем.
Таким образом, мы попадаем в состояние, когда за ошибкой commit-graph verify
не может следовать commit-graph write
, если установлено core.commitGraph=true
, для продолжения необходимо либо вручную удалить график, либо core.commitGraph
нужно установить значение false.
Чтобы избежать этого, измените commit-graph write
кодовый путь, чтобы использовать новый parse_commit_no_graph()
помощник вместо parse_commit()
.
Последний вызовет repo_parse_commit_internal()
с use_commit_graph=1
, как показано в 177722b (commit
: интегрировать график фиксации с анализом фиксации, 2018-04-10, Git v2.18.0-rc0).
Отказ от использования старого графика на некоторое время замедляет запись нового графика, но это разумный способ предотвратить распространение ошибки в существующем графике фиксации.
В Git 2.24+ (3 квартал 2019 г.) график фиксации активен по умолчанию:
См. совершить aaf633c, фиксация c6cc4c5, Деррик Столи (derrickstolee
).
(объединено Junio C Haman o - gitster
- в commit f4f8dfe, 09 сентября 2019 г.)
commit-graph
: включить график фиксации по умолчанию
Функция графа фиксации активно использовалась за последний год или около того с момента ее появления.
Эта функция является критически важным улучшением производительности для репозиториев среднего и большого размера и не наносит значительного ущерба небольшим репозиториям.
Измените значения по умолчанию для core.commitGraph
и gc.writeCommitGraph
на true, чтобы пользователи могли пользоваться этой функцией по умолчанию.
По-прежнему в Git 2.24 (4 квартал 2019 г.) переменная конфигурации сообщает git fetch
о необходимости записи графа фиксации после завершения.
См. фиксацию 50f26bd (3 сентября 2019 г.) по Деррик Столи (derrickstolee
).
(Объединено Junio C Hamano - gitster
- в фиксации 5a53509, 30 сен 2019)
fetch: добавить параметр конфигурации fetch.writeCommitGraph
Функция графа фиксации теперь включена по умолчанию и по умолчанию записывается во время 'git gc
'.
Обычно Git записывает граф фиксации только тогда, когда команда 'git gc --auto
' передает параметр gc.auto
, чтобы он действительно работал. Это означает, что график коммитов обычно отстает от тех, которые используются каждый день.
Чтобы оставаться в курсе последних коммитов, добавьте шаг в 'git fetch
' для написания графика фиксации после получения новых объектов.
Параметр fetch.writeCommitGraph
config позволяет писать разделенный граф фиксации, поэтому в среднем стоимость записи этого файла очень мала. Иногда цепочка фиксации-графа сворачивается до одного уровня, и это может быть медленным для очень больших репозиториев.
Для дополнительного использования измените значение по умолчанию, чтобы оно было истинным, когда feature.experimental
включен.
И все же с Git 2.24 (4 квартал 2019 г.) commit-graph
стал более надежным.
См. commit 6abada1, commit fbab552 (12 сентября 2019 г.), автор Джефф Кинг (peff
).
(Объединено Junio C Hamano - gitster
- a> в commit 098e8c6, 7 октября 2019 г.)
commit-graph
: увеличить DIE_ON_LOAD
проверку до фактического времени загрузки
Фиксация 43d3561 (запись коммит-графа: не умирай, если существующий граф поврежден , 2019-03-25, Git v2.22.0-rc0) добавил переменную среды, которую мы используем только в тестовом наборе, $GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD
.
Но он поставил проверку этой переменной в самом верху prepare_commit_graph()
, который называется каждый раз, когда мы хотим использовать график фиксации.
Что наиболее важно, он появляется до, когда мы проверяем, какой быстрый путь мы уже пытались загрузить?, что означает, что мы в конечном итоге вызываем getenv()
для каждого отдельного использование графика фиксации, а не только при загрузке.
getenv()
может иметь неожиданные побочные эффекты, но здесь это не должно быть проблемой; мы загружаем график лениво, чтобы было ясно, что по крайней мере один вызов этой функции вызовет его.
Но это неэффективно. getenv()
обычно должен выполнять линейный поиск в пространстве окружения.
Мы могли бы запоминать вызов, но еще проще просто перенести проверку на фактический шаг загрузки. Это нормально для нашего единственного пользователя в t5318 и дает небольшое реальное ускорение:
[before]
Benchmark #1: git -C linux rev-list HEAD >/dev/null
Time (mean ± σ): 1.460 s ± 0.017 s [User: 1.174 s, System: 0.285 s]
Range (min … max): 1.440 s … 1.491 s 10 runs
[after]
Benchmark #1: git -C linux rev-list HEAD >/dev/null
Time (mean ± σ): 1.391 s ± 0.005 s [User: 1.118 s, System: 0.273 s]
Range (min … max): 1.385 s … 1.399 s 10 runs
Git 2.24 (4 квартал 2019 г.) также включает исправление регрессии.
См. фиксацию cb99a34, совершить e88aab9 (24 октября 2019 г.), (derrickstolee
).
(Объединено Junio C Hamano - gitster
- a> в commit dac1d83, 4 ноября 2019 г.)
commit-graph
: исправление записи первого графика фиксации во время выборки
Докладчик: Йоханнес Шинделин
Помощник: Джефф Кинг
Помощник: Седер Габор
Подписано: Деррик Столи
Предыдущая фиксация включает в себя неудачный тест на проблему с fetch.writeCommitGraph и выборку в репо с подмодулем. Здесь мы исправляем эту ошибку и устанавливаем для теста значение "test_expect_success"
.
Проблема возникает с этим набором команд, когда удаленное репо на <url>
имеет подмодуль.
Обратите внимание, что --recurse-submodules
не требуется для демонстрации ошибки.
$ git clone <url> test
$ cd test
$ git -c fetch.writeCommitGraph=true fetch origin
Computing commit graph generation numbers: 100% (12/12), done.
BUG: commit-graph.c:886: missing parent <hash1> for commit <hash2>
Aborted (core dumped)
В качестве первоначального исправления я преобразовал код в builtin/fetch.c
, который вызывает write_commit_graph_reachable()
для запуска процесса git commit-graph
записи --reachable --split
. Этот код работал, но мы не хотим, чтобы эта функция работала в долгосрочной перспективе.
Этот тест продемонстрировал, что проблема должна быть связана с внутренним состоянием процесса git fetch.
Метод write_commit_graph()
в commit-graph.c
гарантирует, что коммиты, которые мы планируем написать закрываются из-за достижимости с помощью close_reachable()
.
Этот метод идет от входных коммитов и использует флаг UNINTERESTING
, чтобы отметить, какие коммиты уже были посещены. Это позволяет обходу занять O(N)
время, где N
- это количество коммитов, а не O(P)
время, где P
- количество путей. (Количество путей может быть экспоненциальным числом коммитов.)
Однако флаг UNINTERESTING
используется во многих местах кодовой базы. Этот флаг обычно означает некоторый барьер для остановки обхода фиксации, например, при обходе ревизий для сравнения историй.
Он не часто сбрасывается после завершения обхода, потому что начальные точки этих обходов не имеют флага UNINTERESTING
, и clear_commit_marks()
немедленно остановится.
Это происходит во время вызова «git fetch
» с пульта дистанционного управления. Согласование выборки сравнивает удаленные ссылки с локальными и помечает некоторые коммиты как UNINTERESTING
.
Я тестировал запуск clear_commit_marks_many()
, чтобы очистить флаг НЕПРЕРЫВИМОСТИ внутри close_reachable()
, но подсказки не имели флага, так что это ничего не дало.
Оказывается, виноват метод calculate_changed_submodule_paths()
. Спасибо, Пеф, за указание на эту деталь! В частности, для каждого подмодуля collect_changed_submodules()
выполняет обход ревизий, чтобы, по сути, вести историю файлов в списке подмодулей. Эти метки обхода исправлений фиксируются UNININTERESTING
, если они упрощены без изменения подмодуля.
Вместо этого я наконец пришел к выводу, что мне следует использовать флаг, который не используется ни в какой другой части кода. В commit-reach.c
было определено несколько флагов для обхода фиксации. алгоритмы. Флаг REACHABLE
казался наиболее целесообразным, и, похоже, он фактически не использовался в файле.
Флаг REACHABLE
использовался в ранних версиях _ 115_, но был удален пользователем 4fbcca4 (commit-reach
: make _117 _... linear, 2018-07-20, v2.20.0-rc0).
Добавьте флаг REACHABLE
в commit-graph.c
и используйте его вместо UNINTEREST в close_reachable()
.
Это исправляет ошибку при ручном тестировании.
Параллельная выборка из нескольких пультов в один и тот же репозиторий плохо взаимодействовала с недавним изменением (необязательно) обновления графа фиксации после завершения задания выборки, поскольку эти параллельные выборки конкурируют друг с другом.
Это было исправлено в Git 2.25 (первый квартал 2020 г.).
См. совершить 7d8e72b, commit c14e6e7 (3 ноября 2019 г.), (dscho
).
(Объединено Junio C Hamano - gitster
- a> в commit bcb06e2, 01 декабря 2019 г.)
fetch
: добавьте параметр командной строки --write-commit-graph
Подписано: Йоханнес Шинделин
Эта опция переопределяет настройку конфигурации fetch.writeCommitGraph
, если обе установлены.
А также:
fetch
: избегайте проблем с блокировкой между fetch.jobs/fetch.writeCommitGraph
Подписано: Йоханнес Шинделин
Когда установлены и fetch.jobs
, и fetch.writeCommitGraph
, в настоящее время мы пытаемся написать график фиксации в каждом из параллельных заданий выборки, что часто приводит к сообщениям об ошибках, подобным этому:
fatal: Unable to create '.../.git/objects/info/commit-graphs/commit-graph-chain.lock': File exists.
Давайте избежим этого, отложив запись графа фиксации до тех пор, пока не будут выполнены все задания выборки.
Код для записи файла (ов) разбитого графа фиксации при получении вычисленного фиктивного значения для параметра, используемого при разбиении результирующих файлов, который был исправлен с помощью Git 2.25 (первый квартал 2020 г.).
См. фиксацию 63020f1 (2 января 2020 г.) по Деррик Столи (derrickstolee
).
(Объединено пользователем Junio C Hamano - gitster
- в фиксации 037f067, 06 янв 2020 г.)
commit-graph
: предпочитать значение по умолчанию size_mult
при нулевом значении
Подписано: Деррик Столи
В 50f26bd (fetch
: добавить параметр конфигурации fetch.writeCommitGraph, 2019-09-02 Git v2.24.0-rc0 - слияние, перечисленное в batch # 4), встроенная функция fetch добавила возможность писать график фиксации с использованием функции --split
.
Эта функция создает несколько файлов графика фиксации, и они могут объединяться на основе набора параметров разделения, включая кратный размер.
По умолчанию кратный размер равен 2, что обеспечивает глубину log_2
N графа фиксации цепочка, где N - количество коммитов.
Однако во время догфудинга я заметил, что мои цепочки графиков фиксации становились довольно большими, когда оставались только сборки с помощью 'git fetch
'.
Оказывается, в split_graph_merge_strategy()
для переменной size_mult
по умолчанию используется значение 2, за исключением того, что мы переопределяем ее с помощью split_opts
контекста, если они существуют.
В _141 _, мы создаем такой split_opts,
, но не заполняем его значениями.
Эта проблема возникает из-за двух сбоев:
- Непонятно, можно ли добавить флаг
COMMIT_GRAPH_WRITE_SPLIT
с NULL
split_opts
.
- Если у нас есть
split_opts,
, отличное от NULL, тогда мы отменяем значения по умолчанию, даже если задано нулевое значение.
Исправьте обе эти проблемы.
- Во-первых, не переопределяйте
size_mult
, когда параметры предоставляют нулевое значение.
- Во-вторых, прекратите создавать
split_opts
во встроенной функции выборки.
Обратите внимание, что git log
был нарушен между Git 2.22 (май 2019 г.) и Git 2.27 (2 квартал 2020 г.) при использовании magic pathspec.
Синтаксический анализ командной строки git log :/a/b/
был нарушен около года, и никто не заметил, что был исправлен.
См. фиксацию 0220461 (10 апреля 2020 г.) по Джефф Кинг (peff
).
См. совершить 5ff4b92 (10 апреля 2020 г.) от Junio C Hamano (gitster
) .
(Объединено Junio C Hamano - gitster
- в commit 95ca489, 22 апреля 2020 г.)
sha1-name
: не предполагайте, что хранилище ссылок инициализировано
Автор: Эрико Ролим
c931ba4e (sha1
-name.c``: удалить the_repo
из handle_one_ref()
, 2019 -16, Git v2.22.0-rc0 - слияние, указанное в пакет № 8) заменил использование помощника for_each_ref()
, который работает с основным хранилищем ссылок репозитория по умолчанию. Например, с refs_for_each_ref()
, который может работать с любым экземпляром хранилища ссылок, предполагая, что у экземпляра репозитория, переданного функции, хранилище ссылок уже инициализировано.
Но возможно, что его никто не инициализировал, и в этом случае код завершает разыменование указателя NULL
.
А также:
repository
: отметьте указатель ссылок как частный
Подписано: Джефф Кинг
Указатель refs в репозитории структуры начинает свою жизнь как NULL
, но затем лениво инициализируется, когда к нему обращаются через get_main_ref_store()
.
Тем не менее, вызывающему коду легко забыть об этом и получить к нему прямой доступ, что приводит к работающему коду иногда, но терпит неудачу, если вызывается до того, как кто-либо другой обратится к ссылкам.
Это было причиной ошибки, исправленной 5ff4b920eb (sha1-name
: не предполагайте, что ref store инициализирован, 2020-04-09, Git v2.27.0 - объединить перечислены в пакете № 3). Чтобы избежать подобных ошибок, давайте более четко обозначим поле refs как частное.
person
VonC
schedule
14.04.2018