DOMAIN\username = User Name
Часть слева от знака равенства — это поле "User" из TFVC, а часть справа — соответствующий ему автор в Git.
Как только этот файл готов, необходимо сделать полную копию TFVC проекта:
PS> git tfs clone --with-branches --authors=AUTHORS https://username.visualstudio.com/DefaultCollection $/project/Trunk project_git
Затем вы, возможно, захотите избавиться от строчек с git-tfs-id в сообщениях коммитов. Следующая команда сделает это:
PS> git filter-branch -f --msg-filter 'sed "s/^git-tfs-id:.*$//g"' -- --all
Она использует утилиту sed из пакета git-bash чтобы заменить все строки, начинающиеся с git-tfs-id: на пустые, которые Git проигнорирует.
Теперь всё готово. Можете добавить новый удалённый репозиторий, отправить изменения в него и ваша команда может начинать работу с Git.
Импорт произвольного репозитория
Если вы пользуетесь какой-либо другой системой контроля версий, не перечисленной выше, вам следует поискать инструмент для импорта в Сети — качественные решения доступны для CVS, Clear Case, Visual Source Safe и даже директорий с архивами. Если всё же существующие решения вам не подошли, вы пользуетесь менее известной СКВ или вам нужно больше контроля над процессом импорта — используйте git fast-import. Эта команда читает простые инструкции из потока ввода и записывает данные в Git. Создать Git-объекты таким путём намного проще, чем через низкоуровневые Git-команды или пытаясь воссоздать их вручную (обратитесь к Git изнутри за деталями). Таким образом, вы можете написать небольшой скрипт, считывающий нужную информацию из вашего хранилища и выводящий инструкции в стандартный поток вывода. Затем вы можете запустить эту программу и передать её вывод прямиком в git fast-import.
Для демонстрации, мы с вами напишем простой скрипт для импорта. Предположим, вы работаете в директории current и периодически создаёте резервные копии в директориях вида back_YYYY_MM_DD, и хотите перенести данные в Git. Структура директорий выглядит подобным образом:
$ls /opt/import_from
back_2014_01_02
back_2014_01_04
back_2014_01_14
back_2014_02_03
current
Чтобы успешно импортировать репозиторий, давайте вспомним, как Git хранит данные. Как вы наверное помните, Git по сути представляет собой связанный список ревизий, каждая из которых указывает на слепок состояния. Всё что от вас требуется, это указать fast-import'у на данные для создания слепков и порядок их применения. Итак, мы пробежимся по всем слепкам, создадим коммит для каждого из них и свяжем каждый новый коммит с предыдущим.
Как и в разделе An Example Git-Enforced Policy, мы проделаем это на Ruby, потому что это мы любим этот язык и его понять. Вы можете использовать любой другой язык — всё что требуется, это вывести нужную информацию в стандартный поток вывода. Если вы работаете на Windows, будьте особо осторожными с переводами строк: fast-import ожидает лишь символы перевода строки (LF), но не возврат каретки + перевод строки (CRLF), как принято в Windows.
Для начала зайдём в исходную директорию и определим поддиректории, содержащие состояния проекта в разные моменты времени, которые будут использованы для построения соответствующих коммитов. Вы поочерёдно посетите каждую из них и выполните команды, необходимые для экспорта. Примерно так:
last_mark = nil
# loop through the directories
Dir.chdir(ARGV[0]) do
Dir.glob( "*" ).each do|dir|
next ifFile.file?(dir)
# move into the target directory
Dir.chdir(dir) do
last_mark = print_export(dir, last_mark)
end
end
end
Вы выполняете функцию print_export внутри каждой директории. Она принимает на вход текущую директорию и результат предыдущего вызова и помечает текущую директорию, возвращая данные для последующих вызовов; таким образом связывая коммиты. Пометки используются для связи коммитов вместе. Итак, первым делом нужно сгенерировать метку по директории:
mark = convert_dir_to_mark(dir)
Создадим массив директорий и используем индекс директории в нём как метку; это удобно, ведь метка должна быть целым числом. Мы написали такой код:
$marks = []
defconvert_dir_to_mark(dir)
if!$marks.include?(dir)
$marks << dir
end
($marks.index(dir) + 1).to_s
end
Теперь, когда у нас есть целочисленная метка для коммита, нужна дата. У нас она хранится в имени директории, придётся достать её оттуда. Следующая строка в print_export:
date = convert_dir_to_date(dir)
where convert_dir_to_date is defined as
defconvert_dir_to_date(dir)
ifdir == 'current'
returnTime.now().to_i
else
dir = dir.gsub( 'back_' , '' )
(year, month, day) = dir.split( '_' )
returnTime.local(year, month, day).to_i
Читать дальше