改写历史 git filter-branch 创建/拆分为子模块/子项目 [英] Rewrite history git filter-branch create / split into submodules / subprojects

查看:25
本文介绍了改写历史 git filter-branch 创建/拆分为子模块/子项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在将一个 cvs 项目导入 git.
导入后,我想重写历史记录以将现有目录移动到单独的子模块中.

假设我有一个这样的结构:

<代码>文件1
文件2
文件3
目录1
目录2
图书馆

现在我想重写历史记录,以便目录 library 始终是一个 git 子模块.比如说,把指定的目录拆分成自己的子模块/子项目

这是我当前的代码:

File rewrite-submodule(被调用)

cd 项目git filter-branch --tree-filter $PWD/../$0-tree-filter --tag-name-filter cat -- --all

文件 rewrite-submodule-tree-filter

<前>#!/bin/bash函数 gitCommit(){取消设置 GIT_DIR取消设置 GIT_WORK_TREEgit add -A如果 [ -n "$(git diff --cached --name-only)" ]然后# 要提交的东西git commit -F $_msg菲}_git_dir=$GIT_DIR_git_work_tree=$GIT_WORK_TREE取消设置 GIT_DIR取消设置 GIT_WORK_TREE_dir=$PWD如果 [ -d "图书馆" ]然后_msg=$(临时文件)git 日志 ${GIT_COMMIT}^!--format="%B" > $_msggit rm -r --cached lib光盘库如果 [ -d ".git" ]然后提交别的混帐初始化提交菲光盘..导出 GIT_DIR=$_git_dir导出 GIT_WORK_TREE=$_git_work_treegit 子模块添加 -f ./lib菲GIT_DIR=$_git_dirGIT_WORK_TREE=$_git_work_tree

此代码创建 .gitmodules 文件,但不创建子模块提交条目(行 Subproject commit , output by git diff)主存储库和目录 library 中的文件仍然在主存储库中进行版本控制,而不是在子项目存储库中.

提前感谢您的任何提示

.gitmodules 看起来像这样:
<前>[子模块库"]路径 = 库网址 = ./图书馆

解决方案

我解决了我自己的问题,这里是解决方案:

git-submodule-split library another_library

脚本git-submodule-split:

<前>#!/bin/bash设置 -eu如果 [ $# -eq 0 ]然后echo "用法:$0 submodules-to-split"菲出口 _tmp=$(mktemp -d)导出 _libs="$@"因为我在 $_libs做mkdir -p $_tmp/$i完毕git filter-branch --commit-filter '函数 gitCommit(){git add -A如果 [ -n "$(git diff --cached --name-only)" ]然后git commit -F $_msg菲>/dev/null# 来自 git-filter-branchgit checkout-index -f -u -a ||死无法检查索引"# $commit 删除的文件现在仍然在工作树中;# 删除它们,否则它们会被再次添加git clean -d -q -f -x_git_dir=$GIT_DIR_git_work_tree=$GIT_WORK_TREE_git_index_file=$GIT_INDEX_FILE取消设置 GIT_DIR取消设置 GIT_WORK_TREE取消设置 GIT_INDEX_FILE_msg=$(临时文件)猫/dev/stdin > $_msg因为我在 $_libs做如果 [ -d "$i" ]然后取消设置 GIT_DIR取消设置 GIT_WORK_TREE取消设置 GIT_INDEX_FILE光盘 $i如果 [ -d ".git" ]然后提交别的git 初始化 >/dev/null提交菲光盘..rsync -a -rtu $i/.git/$_tmp/$i/.git/导出 GIT_DIR=$_git_dir导出 GIT_WORK_TREE=$_git_work_tree导出 GIT_INDEX_FILE=$_git_index_filegit rm -q -r --cached $igit 子模块添加 ./$i >/dev/nullgit 添加 $i菲完毕rm $_msg导出 GIT_DIR=$_git_dir导出 GIT_WORK_TREE=$_git_work_tree导出 GIT_INDEX_FILE=$_git_index_file如果 [ -f ".gitmodules" ]然后git add .gitmodules菲_new_rev=$(git 写树)转移git commit-tree "$_new_rev" "$@";' --tag-name-filter 猫 -- --all因为我在 $_libs做如果 [ -d "$_tmp/$i/.git" ]然后rsync -a -i -rtu $_tmp/$i/.git/$i/.git/光盘 $igit reset --hard光盘..菲完毕rm -r $_tmpgit for-each-ref refs/original --format="%(refname)" |读我的时候;做 git update-ref -d $i;完毕git reflog expire --expire=now --allgit gc --aggressive --prune=now

I am currently importing a cvs project into git.
After importing, i want to rewrite the history to move an existing directory into a seperate submodule.

Suppose i have a structure like this:

file1
file2
file3
dir1
dir2
library

Now i want to rewrite the history so that the directory library is always a git submodule. Say, split out specified directories into their own submodules / subprojects

This is my currently code:

File rewrite-submodule (which is called)

cd project
git filter-branch --tree-filter $PWD/../$0-tree-filter --tag-name-filter cat -- --all

File rewrite-submodule-tree-filter

    #!/bin/bash

    function gitCommit()
    {
        unset GIT_DIR
        unset GIT_WORK_TREE
        git add -A
        if [ -n "$(git diff --cached --name-only)" ]
        then
            # something to commit
            git commit -F $_msg
        fi
    }

    _git_dir=$GIT_DIR
    _git_work_tree=$GIT_WORK_TREE
    unset GIT_DIR
    unset GIT_WORK_TREE
    _dir=$PWD

    if [ -d "library" ]
    then
        _msg=$(tempfile)
        git log ${GIT_COMMIT}^! --format="%B" > $_msg
        git rm -r --cached lib
        cd library
        if [ -d ".git" ]
        then
            gitCommit
        else
            git init
            gitCommit
        fi
        cd ..
        export GIT_DIR=$_git_dir
        export GIT_WORK_TREE=$_git_work_tree
        git submodule add -f ./lib
    fi

    GIT_DIR=$_git_dir
    GIT_WORK_TREE=$_git_work_tree
    

This code creates the .gitmodules file, but not the submodule commit entry (the line Subproject commit <sha1-hash>, output by git diff) in the main repository and the files in directory library are still versioned in the main repository and not in the subproject repository.

Thanks in advance for any hint

The .gitmodules look like this:

    [submodule "library"]
        path = library
        url = ./library
    

解决方案

I resolved my own question, here is the solution:

git-submodule-split library another_library

Script git-submodule-split:

    #!/bin/bash

    set -eu

    if [ $# -eq 0 ]
    then
        echo "Usage: $0 submodules-to-split"
    fi

    export _tmp=$(mktemp -d)
    export _libs="$@"
    for i in $_libs
    do
        mkdir -p $_tmp/$i
    done

    git filter-branch --commit-filter '
    function gitCommit()
    {
        git add -A
        if [ -n "$(git diff --cached --name-only)" ]
        then
            git commit -F $_msg
        fi
    } >/dev/null

    # from git-filter-branch
    git checkout-index -f -u -a || die "Could not checkout the index"
    # files that $commit removed are now still in the working tree;
    # remove them, else they would be added again
    git clean -d -q -f -x

    _git_dir=$GIT_DIR
    _git_work_tree=$GIT_WORK_TREE
    _git_index_file=$GIT_INDEX_FILE
    unset GIT_DIR
    unset GIT_WORK_TREE
    unset GIT_INDEX_FILE

    _msg=$(tempfile)
    cat /dev/stdin > $_msg
    for i in $_libs
    do
        if [ -d "$i" ]
        then
            unset GIT_DIR
            unset GIT_WORK_TREE
            unset GIT_INDEX_FILE
            cd $i
            if [ -d ".git" ]
            then
                gitCommit
            else
                git init >/dev/null
                gitCommit
            fi
            cd ..
            rsync -a -rtu $i/.git/ $_tmp/$i/.git/
            export GIT_DIR=$_git_dir
            export GIT_WORK_TREE=$_git_work_tree
            export GIT_INDEX_FILE=$_git_index_file
            git rm -q -r --cached $i
            git submodule add ./$i >/dev/null
            git add $i
        fi
    done
    rm $_msg
    export GIT_DIR=$_git_dir
    export GIT_WORK_TREE=$_git_work_tree
    export GIT_INDEX_FILE=$_git_index_file

    if [ -f ".gitmodules" ]
    then
        git add .gitmodules
    fi

    _new_rev=$(git write-tree)
    shift
    git commit-tree "$_new_rev" "$@";
    ' --tag-name-filter cat -- --all

    for i in $_libs
    do
        if [ -d "$_tmp/$i/.git" ]
        then
            rsync -a -i -rtu $_tmp/$i/.git/ $i/.git/
            cd $i
            git reset --hard
            cd ..
        fi
    done
    rm -r $_tmp

    git for-each-ref refs/original --format="%(refname)" | while read i; do git update-ref -d $i; done

    git reflog expire --expire=now --all
    git gc --aggressive --prune=now

    

这篇关于改写历史 git filter-branch 创建/拆分为子模块/子项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆