Как хранятся и рассчитываются истории контроля версий? - PullRequest
11 голосов
/ 11 января 2012

Рассмотрим этот простой код Python, который демонстрирует очень простой дизайн управления версиями для диктонары:

def build_current(history):
    current = {}
    for action, key, value in history:
        assert action in ('set', 'del')
        if action == 'set':
            current[key] = value
        elif action == 'del':
            del current[key]
    return current

history = []
history.append(('set', '1', 'one'))
history.append(('set', '2', 'two'))
history.append(('set', '3', 'three'))
print build_current(history)
history.append(('del', '2', None))
history.append(('set', '1', 'uno'))
history.append(('set', '4', 'four'))
print build_current(history)
for action, key, value in history:
    if key == '2':
        print '(%s, %s, %s)' % (action, key, value)

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

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

Мой вопрос: какие существуют другие подходы для хранения историй в системе управления версиями?Возможно, можно использовать «обратную сборку»?Это может позволить пользователям загружать только последние версии без необходимости всей истории.Я также видел несколько различных форматов для хранения истории, а именно: наборы изменений, снимки и исправления.Каковы различия между наборами изменений, моментальными снимками и исправлениями?

Из современных популярных элементов управления версиями, как они хранят свою историю и каковы преимущества их различных конструкций?

Ответы [ 3 ]

11 голосов
/ 12 января 2012

Вы упомянули эти 3 способа хранения (файл) -истории:

  1. patch : патч (обычно текстовый, но возможны также двоичные патчи) представляет разницу между двумя файлами. Это вывод команды unix diff и может быть применен командой unix patch . Многие системы управления версиями используют патчи для хранения истории файлов (например, SVN, CVS, GIT ..). Иногда эти пятна технически называют «дельта» как греческая буква «Δ» , описывающая разницу двух вещей.
  2. changeset : набор изменений - это термин, объединяющий изменения, «принадлежащие друг другу», в разные файлы в одном объекте. Не все системы управления версиями поддерживают наборы изменений (наиболее известные CVS и SourceSafe). Разработчик использует наборы изменений, чтобы избежать неправильных сборок (например: изменить сигнатуру метода в одном файле, изменить вызов во втором файле. Для запуска программы необходимо иметь оба изменения на месте, в противном случае вы получите ошибку). См. Также здесь разницу между наборами изменений и патчем .
  3. снимки : полные копии состояния этого файла / файловой системы на данный момент. Они обычно довольно большие, и их использование зависит от характеристик производительности. Снимок всегда избыточен списку исправлений, однако для быстрого извлечения информации иногда системы управления версиями смешивают или объединяют исправления и снимки

Subversion использует прямые дельты (или патчи) в репозиториях FSFS и обратные дельты в репозиториях BDB. Обратите внимание, что эти реализации имеют разные характеристики производительности:

  • Дельта форварда быстрая при совершении, но медленная при оформлении заказа (как «текущая» версия должна быть реконструирована)

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

Также обратите внимание, что FSFS использует «пропускающий дельта» алгоритм, который минимизирует скачки для восстановления конкретной версии. Эта пропускающая дельта, однако, не оптимизирована по размеру как снимки ртути; он просто сводит к минимуму количество «ревизий», необходимых для создания полной версии, независимо от общего размера.

Здесь небольшой ascii art (скопированный из спецификации) файл с 9 ревизиями:

0 <- 1    2 <- 3    4 <- 5    6 <- 7
0 <------ 2         4 <------ 6
0 <---------------- 4
0 <------------------------------------ 8 <- 9

где "0 <- 1" означает, что дельта-база для ревизии 1 - это ревизия 0. </p>

Количество прыжков не более log (N) для N ревизий.

Также очень приятный эффект для FSFS заключается в том, что более старая ревизия будет записана только один раз , и после этого они будут прочитаны только при дальнейших действиях. Вот почему репозитории Subversion очень стабильны: если у вас нет сбоя HW на жестком диске, вы сможете получить работающий репозиторий, даже если в последнем коммите произошел какой-то сбой: у вас все еще есть более старые ревизии.

В BDB Backend вы постоянно переписываете текущую версию проверок / фиксаций, что делает этот процесс подверженным повреждению данных. Кроме того, поскольку вы сохраняете полный текст только в текущей редакции, повреждение данных при фиксации, вероятно, разрушит большую часть вашей истории.

8 голосов
/ 12 января 2012

Я думаю, что Subversion предприняла несколько попыток обратной сборки. Но я могу объяснить то, что я знаю лучше: снимки Mercurial.

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

Это означает, что вам никогда не нужно читать текст более чем в 3 раза, чтобы получить любую ревизию.

Вы можете найти более подробную информацию в Книге ртути .

4 голосов
/ 15 июля 2012

В качестве более общего ответа вам нужно дифференцировать CVCS (централизованные VCS, такие как CVS, SVN, Perforce, ClearCase, ...) от DVCS ( распределенные VCS, такие как Git или Mercurial ).
Они включают различные рабочие процессы и использование .

В частности, обмен данными между клиентом CVCS и его сервером будет важнее, чем с DVCS (который действительно нуждается в дельте при нажатии или извлечении всего репо)

Именно поэтому дельта очень важна для большинства операций в CVCS, важна только для определенных операций и по разным причинам в DVCS.

Дельты описаны в двух книгах Эрика Синка:

Репозиторий = Файловая система * Время

Дерево - это иерархия папок и файлов.Дельта - это разница между двумя деревьями.Теоретически, эти два дерева не должны быть связаны.Однако на практике единственная причина, по которой мы вычисляем разницу между ними, заключается в том, что одно из них является производным от другого.Некоторые разработчики начали с дерева N и внесли одно или несколько изменений, в результате чего появилось дерево N + 1.

Мы можем рассматривать дельту как набор изменений.Фактически, многие инструменты SCM используют термин «набор изменений» именно для этой цели.Набор изменений - это просто список изменений, которые выражают разницу между двумя деревьями.

Важен смысл дельты (см. этот поток ): прямая дельта или обратная дельта.

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

Вы можете увидеть эволюцию «старого»"VCS в Понимание Эриком Рэймондом систем контроля версий .

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

Не забывайте, что дельта-управление также влияет на Направленные ациклические графы (DAG) создан для представления истории (см. « Направление стрелок в книге ProGit » и неудобно позади DAG ).

вы можете найти особенности о дельта-управлении для:

Veracity поддерживает два типа DAG:

  • Дерево DAG хранит историю версий структуры каталогов из файловой системы.Каждый узел группы доступности базы данных представляет одну версию всего дерева.

  • База данных (или «дБ») DAG хранит историю версий базы данных или список записей.Каждый узел группы обеспечения доступности баз данных представляет одно состояние всей базы данных.

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

...