重写历史git filter-branch创建/拆分为子模块/子项目 [英] Rewrite history git filter-branch create / split into submodules / subprojects
问题描述
我目前正在将一个cvs项目导入到git中。
导入后,我想重写历史记录以将现有目录移动到单独的子模块中。
假设我有这样的结构:
file1
file2
file3
dir1
dir2
图书馆
现在我想重写历史记录,以便目录 library
始终是一个git子模块。说,将指定的目录拆分到他们自己的子模块/子项目中
这是我目前的代码:
b> rewrite-submodule (称为)
cd项目
git filter-branch - tree-filter $ PWD /../$ 0-tree-filter --tag-name-filter cat - --all
文件 rewrite-submodule-tree-filter
#!/ bin / bash
函数gitCommit()
{
unset GIT_DIR
unset GIT_WORK_TREE
git add -A
if [-n$(git diff - -cached --name-only)]
然后
#提交的东西
git commit -F $ _msg
fi
}
_git_dir = $ GIT_DIR
_git_work_tree = $ GIT_WORK_TREE
未设置GIT_DIR
未设置GIT_WORK_TREE
_dir = $ PWD
如果[-dlibrary]
然后
_msg = $(tempfile)
git log $ {GIT_COMMI T】^! --format =%B> $ _msg
git rm -r --cached lib
cd库
if [-d.git]
然后
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
此代码创建.gitmodules文件,但不会创建子模块提交条目( Subproject commit< sha1-hash>
,由<$主库中的c $ c> git diff ),目录 library
中的文件仍在版本库中,而不是在子项目库中。
预先感谢任何提示
.gitmodules看起来像这样:
[submodulelibrary]
path = libr ary
url = ./library
问题,这里是解决方案:
git-submodule-split library another_library
脚本 git-submodule-split
:
# !/ bin / bash
set -eu
$ b $ if if [$#-eq 0]
then
echo用法:$ 0 submodules-to- split
fi
export _tmp = $(mktemp -d)
export _libs =$ @
for $ in $ _libs
do
mkdir -p $ _tmp / $ i
完成
git filter-branch --commit-filter'
函数gitCommit()
{
git add -A
if [-n$(git diff --cached --name-only)]
then
git commit -F $ _msg
fi
}> / dev / null
#从git-filter-branch
git 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
unset GIT_DIR
unset GIT_WORK_TREE
unset GIT_INDEX_FILE
_msg = $(tempfile)$ b $ 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]
然后
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
$ b $ if [-f.gitmodules]
然后
git add .gitmodules
fi
_new_rev = $(git write-tree)
shift
git commit-tree$ _new_rev$ @;
'--tag-name-filter cat - --all
for $ in $ _libs
do
if [-d$ _tmp / $ i /.git]
然后
rsync -a -i -rtu $ _tmp / $ i / .git / $ i / .git /
cd $ i
git reset - -hard
cd ..
fi
完成
rm -r $ _tmp
git for-each-ref refs / original --format = %(refname)|同时阅读我;做git update-ref -d $ i; done
git reflog expire --expire = now --all
git gc --aggressive --prune = now
$ b
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屋!