Git команды для автоматического объединения поддерева проекта с подмодулями? - PullRequest
2 голосов
/ 25 марта 2011

Я нашел С помощью Git, как лучше всего объединить поддерево с внешним проектом, в котором есть субмодули? , но, будучи связанным, он не отвечает на мой вопрос.

Предположим, у меня есть мой родительский проект и мой дочерний проект, который содержит подмодули. Как объединить дочерний проект в дочерний проект родительского проекта и сохранить работоспособность ссылок на подмодули?

Я пробовал такие вещи, как:

git remote add -f child_remote git://github.com/me/child.git
git checkout -b child_branch child_remote/master
git submodule init
git submodule update
git checkout master
git read-tree --prefix=child_directory/ -u child_branch

Но дерево чтения теряет подмодули, а .gitmodules появляется только в подкаталоге. Когда я пытаюсь выполнить инициализацию подмодуля git и обновить подмодуль git, я получаю сообщения об ошибках типа «Не найдено сопоставление подмодуля в .gitmodules для пути« child_directory / submodule_directory »».

Я также пытался изменить инструкции на http://help.github.com/subtree-merge/ для работы с подмодулями, но безрезультатно.

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

Ответы [ 2 ]

0 голосов
/ 29 декабря 2011

Почему бы не использовать субмодули в вашем проекте?Теперь вы можете использовать 'git submodule update --recursive` по всем направлениям.

Также есть git-slave, чтобы помочь вам автоматизировать ветки через подмодули.

0 голосов
/ 13 декабря 2011

Вы можете либо изменить пути в .gitmodules, а затем сделать git submodule init && git submodule update, либо вы можете преобразовать подмодули в поддерево.Последняя опция включает в себя какой-то сценарий, потому что не существует автоматического способа сделать это.

При использовании сценария оболочки вы можете использовать эти функции для получения подмодулей и их имен (из источника git-submodules):

# This lists the unmerged submodules
module_list()
{
    git ls-files --error-unmatch --stage -- "$@" |
    perl -e '
    my %unmerged = ();
    my ($null_sha1) = ("0" x 40);
    while (<STDIN>) {
        chomp;
        my ($mode, $sha1, $stage, $path) =
            /^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
        next unless $mode eq "160000";
        if ($stage ne "0") {
            if (!$unmerged{$path}++) {
                print "$mode $null_sha1 U\t$path\n";
            }
            next;
        }
        print "$_\n";
    }
    '
}

# This gets the submodule's name from the .gitignore file in your webroot
module_name()
{
    # Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
    re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
    name=$( git config -f $2/.gitmodules --get-regexp '^submodule\..*\.path$' |
        sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
    test -z "$name" &&
    die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$path'")"
    echo "$name"
}

Затем, когда вы итерируете результаты, вы можете извлечь имя и URL-адрес для использования в поддеревьях.

module_list | while read mode sha1 stage path
do
    #the path as your repo sees it
    full_path=$path

    #The path as .gitmodules in your child_directory sees it
    fake_path=${path[*]/[child_directory]\//}

    #Get the name of the submodule
    stupid_name=$(module_name "$fake_path" "[child_directory]")

    #Get the git URL from the .gitmodules file
    git_url=$(git config -f [child_directory]/.gitmodules submodule."$stupid_name".url)

    #Gets the clean name to use as remote name
    new_remote=$(echo $git_url | cut -d. -f2 | cut -d/ -f2- | cut -d/ -f2)

    #Remove the submodules folder
    rm -rf $path 

    #Add the subtree
    git remote add -f $new_remote $git_url
    git merge -s ours --no-commit $new_remote/master 
    git read-tree --prefix=$full_path/ -u $new_remote/master
    git commit -m "$new_remote merged in $full_path"
done 

Я уверен, что есть способ лучшеделая это, но это дает представление о том, что должно быть сделано

...