2013-11-30 3 views
0

На нашем сервере у нас есть производственный репозиторий git с некоторыми собственными рабочими потоками вокруг него, которые, как правило, содержат важные коммиты только в некотором reflog. Для целей резервного копирования мы хотим синхронизировать весь репозиторий со вторым хранилищем.Синхронизация всех объектов двух репозиториев git

Один из способов был бы простым git push --all. К сожалению, это будет только толкать объекты, на которые ссылается какой-то известный ref, игнорируя те, которые упоминаются только некоторыми reflog. Есть ли способ сообщить git push, чтобы натолкнуть рефлоги (и соответствующие коммиты!) Тоже? (В настоящее время я могу только подумать о том, чтобы вручную создать слияние фальшивого осьминогов со всеми записями reflog.)

Другим способом может быть резервное копирование на уровне файловой системы, например rsync. Это, вероятно, будет работать, но репозитории довольно большие, и git может переупаковать свои коммиты. Поэтому это может занять много времени.

Есть ли способ перечисления всех объектов в обоих хранилищах, их сравнения и передачи только отсутствующих объектов? Есть ли какая-то встроенная функция для такого рода задач? Какой был бы лучший способ сделать это вручную, иначе?

+0

http://stackoverflow.com/questions/14370929/how-do-i-keep-two-git-repositories-in-sync – eRIZ

+0

Нет, этот полностью не связан. – michas

+0

Полное репо содержится в папке '.git'. Если вы скопируете это в другое место, вы будете эффективно копировать все, включая reflog, которые являются лишь некоторыми текстовыми файлами в '.git/logs'. –

ответ

0

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

Но, не спрашивая о своем процессе;) Я не верю, что есть команда, которая дает вам именно то, что вы ищете (полный список объектов в двух хранилищах). Самый близкий, о котором я могу думать, - это git reflag, который принимает все параметры журнала для фильтрации и форматирования объектов в reflag. Если вы можете сформулировать соответствующий запрос для журнала, возможно, вы могли бы выводить только те объекты фиксации, которые вы находите «важными», но не указаны в каком-либо другом ref, и передаете эти результаты в объекты git-pack. (Ваша идея слияния осьминога является многообещающей в качестве способа их идентификации)

+0

Ну, это не «мой процесс». Это то, что делает «корпоративное программное обеспечение». Блокировки явно настроены так, чтобы никогда не истекать. Предоставление каждой записи reflog явного тега приведет к множеству тегов. Вот почему моя единственная идея состояла в том, чтобы объединить их, чтобы иметь возможность охватить их одним рефером. – michas

0

Нет ничего, что могло бы вызвать (или потянув) рефлоги, но было бы легко «подделать» его, используя иерархическую природу refs/ пространство для временного (или, возможно, даже не временного) исправления и нажатия на них. Затем вы можете запустить пост-push-скрипт - возможно, даже сделайте это непосредственно из post-receive-для создания нужных рефлогов на другом конце, используя git update-ref.

Предположим (для целей эскиза дизайна) вы выбираете refs/sync/ как верхний уровень вашего нового пространства имен. Тогда:

# find reflogs - change this to use the ones you care about 
unfiltered=$(
    for refname in $(cd $(git rev-parse --git-dir)/logs && 
      find * -type f -print); do 
     echo $refname 
    done 
) 

filtered=... # something ... 

filtered="HEAD refs/heads/master" # for now 

for reflog in $filtered; do 
    # change name from (.*)@{([0-9]+)} to \1/\2 
    # (keep commit ID at left) 
    git reflog --no-abbrev $reflog | 
     sed -n 's,\([^ ]*\) \(.*\)@{\([0-9][0-9]*\)}:.*,\1 \2/\3,p' 
done 

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

while read hash name; do 
    git update-ref -m 'create for transport' refs/sync/$name $hash 
done 

Теперь вы можете git push в refs/sync/ пространство имен к удаленное, а затем удалить все refs/sync/ имен (или удалить те, которые созданы здесь, или просто удалить все refs/sync/ имен фронта-вы можете сделать это в любом случае в случае, если один из этих обновлений последовательностей прерываются):

git for-each-ref --format 'git update-ref -d %(refname)' refs/sync/ | sh 

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

Как говорится в другом ответе, в зависимости от того, что в значительной степени связано с рефлогими, возможно, это не все так мудро. Вы можете использовать приведенные выше методы, чтобы превратить существующие записи reflog в нечто более постоянное (например, теги, которые уже существуют в refs/tags/; возможно, вы можете использовать подмножество именное пространство, например refs/tags/autotag/NNN).

Смежные вопросы