pri*_*ohn 125 git git-filter-branch
这个问题基于Detach子目录到单独的Git存储库中
我想分离一对,而不是分离一个子目录.例如,我当前的目录树如下所示:
/apps
/AAA
/BBB
/CCC
/libs
/XXX
/YYY
/ZZZ
Run Code Online (Sandbox Code Playgroud)
而我想这样做:
/apps
/AAA
/libs
/XXX
Run Code Online (Sandbox Code Playgroud)
该--subdirectory-filter参数git filter-branch将无法工作,因为它在第一次运行时除去了给定目录之外的所有内容.我认为使用--index-filter所有不需要的文件的参数会起作用(尽管很乏味),但如果我尝试不止一次运行它,我会得到以下消息:
Cannot create a new backup.
A previous backup already exists in refs/original/
Force overwriting the backup with -f
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?TIA
Dav*_*ley 143
不必处理子shell并使用ext glob(如kynan所建议的那样),尝试这种更简单的方法:
git filter-branch --index-filter 'git rm --cached -qr --ignore-unmatch -- . && git reset -q $GIT_COMMIT -- apps/AAA libs/XXX' --prune-empty -- --all
Run Code Online (Sandbox Code Playgroud)
chf*_*hfw 38
计划是将各个目录拆分为自己的存储库,然后将它们合并在一起.以下手动步骤不使用极客使用的脚本,而是易于理解的命令,可以帮助将额外的N个子文件夹合并到另一个单独的存储库中.
划分
让我们假设你的原始回购是:original_repo
1 - 拆分应用程序:
git clone original_repo apps-repo
cd apps-repo
git filter-branch --prune-empty --subdirectory-filter apps master
Run Code Online (Sandbox Code Playgroud)
2 - 拆分库
git clone original_repo libs-repo
cd libs-repo
git filter-branch --prune-empty --subdirectory-filter libs master
Run Code Online (Sandbox Code Playgroud)
如果您有两个以上的文件夹,请继续.现在你将有两个新的和临时的git存储库.
通过合并应用程序和库来征服
3 - 准备全新的回购:
mkdir my-desired-repo
cd my-desired-repo
git init
Run Code Online (Sandbox Code Playgroud)
而且您需要至少进行一次提交.如果应该跳过以下三行,您的第一个仓库将立即显示在您的仓库的根目录下:
touch a_file_and_make_a_commit # see user's feedback
git add a_file_and_make_a_commit
git commit -am "at least one commit is needed for it to work"
Run Code Online (Sandbox Code Playgroud)
提交临时文件后,merge后面部分中的命令将按预期停止.
从用户的反馈以代替添加一个随机文件等a_file_and_make_a_commit,你可以选择添加.gitignore,或README.md等
4 - 首先合并应用程序repo:
git remote add apps-repo ../apps-repo
git fetch apps-repo
git merge -s ours --no-commit apps-repo/master # see below note.
git read-tree --prefix=apps -u apps-repo/master
git commit -m "import apps"
Run Code Online (Sandbox Code Playgroud)
现在您应该在新存储库中看到apps目录.git log应显示所有相关的历史提交消息.
注:克里斯下面提到的意见,对新版本(> = 2.9)的git的,你需要指定--allow-unrelated-histories用git merge
5 - 以相同的方式合并libs repo:
git remote add libs-repo ../libs-repo
git fetch libs-repo
git merge -s ours --no-commit libs-repo/master # see above note.
git read-tree --prefix=libs -u libs-repo/master
git commit -m "import libs"
Run Code Online (Sandbox Code Playgroud)
如果您有超过2个repos进行合并,请继续.
kyn*_*nan 27
你为什么要跑filter-branch多次?你可以在一次扫描中完成所有操作,所以不需要强制它(注意你需要extglob在shell中启用它才能工作):
git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch $(ls -xd apps/!(AAA) libs/!(XXX))" --prune-empty -- --all
Run Code Online (Sandbox Code Playgroud)
这应该摆脱不需要的子目录中的所有更改并保留所有分支和提交(除非它们仅影响已修剪的子目录中的文件--prune-empty) - 没有重复提交等问题.
执行此操作后,不需要的目录将被列为未跟踪git status.
这$(ls ...)是必要的,extglob它由shell而不是索引过滤器评估,索引过滤器使用sh内置eval(在哪里extglob不可用).请参阅如何在git中启用shell选项?有关这方面的进一步细节.
小智 26
我遇到了类似的问题,在查看了此处列出的各种方法后,我发现了git-filter-repo。在此处的官方 git 文档中,建议将其作为 git-filter-branch 的替代方案。
要从现有存储库中的目录子集创建新存储库,您可以使用以下命令:
git filter-repo --path <file_to_keep>
Run Code Online (Sandbox Code Playgroud)
通过链接多个文件/文件夹来过滤它们:
git filter-repo --path keepthisfile --path keepthisfolder/
Run Code Online (Sandbox Code Playgroud)
因此,要回答原始问题,使用 git-filter-repo 您只需要以下命令:
git filter-repo --path apps/AAA/ --path libs/XXX/
Run Code Online (Sandbox Code Playgroud)
pri*_*ohn 20
在这里回答我自己的问题......经过大量的反复试验.
我设法使用git subtree和组合做到这一点git-stitch-repo.这些说明基于:
首先,我将要保留的目录拉出到他们自己的独立存储库中:
cd origRepo
git subtree split -P apps/AAA -b aaa
git subtree split -P libs/XXX -b xxx
cd ..
mkdir aaaRepo
cd aaaRepo
git init
git fetch ../origRepo aaa
git checkout -b master FETCH_HEAD
cd ..
mkdir xxxRepo
cd xxxRepo
git init
git fetch ../origRepo xxx
git checkout -b master FETCH_HEAD
Run Code Online (Sandbox Code Playgroud)
然后我创建了一个新的空存储库,并将最后两个导入/拼接到其中:
cd ..
mkdir newRepo
cd newRepo
git init
git-stitch-repo ../aaaRepo:apps/AAA ../xxxRepo:libs/XXX | git fast-import
Run Code Online (Sandbox Code Playgroud)
这创建了两个分支,master-A并且master-B每个分支都保存了一个拼接回购的内容.要将它们组合起来并进行清理:
git checkout master-A
git pull . master-B
git checkout master
git branch -d master-A
git branch -d master-B
Run Code Online (Sandbox Code Playgroud)
现在我不太确定如何/何时发生这种情况,但是在第一次checkout和之后pull,代码会神奇地合并到主分支中(对此处发生的事情的任何见解都表示赞赏!)
一切似乎都按预期工作,除非我查看newRepo提交历史记录,当变更集影响到apps/AAA和时,都会有重复libs/XXX.如果有办法删除重复项,那么它将是完美的.
我写了一个git过滤器来解决这个问题.它有着名的git_filter,位于github:
https://github.com/slobobaby/git_filter
它基于优秀的libgit2.
我需要拆分一个包含许多提交的大型存储库(~100000),基于git filter-branch的解决方案需要几天才能运行.git_filter花了一分钟做同样的事情.
git splits是一个bash脚本,它是git branch-filter我作为git扩展创建的包装器,基于jkeating的解决方案.
这完全是为了这种情况.对于您的错误,请尝试使用该git splits -f选项强制删除备份.因为git splits在新分支上运行,所以它不会重写当前分支,因此备份是无关紧要的.有关更多详细信息,请参阅自述文件,并确保在repo的复制/克隆中使用它(以防万一!).
git splits.将目录拆分为本地分支
#change into your repo's directory
cd /path/to/repo
#checkout the branch
git checkout XYZ
#split multiple directories into new branch XYZ
git splits -b XYZ apps/AAA libs/ZZZ
在某处创建一个空的repo.我们假设我们已经创建了一个xyz在GitHub上调用的具有路径的空仓库:git@github.com:simpliwp/xyz.git
推送到新的回购.
#add a new remote origin for the empty repo so we can push to the empty repo on GitHub
git remote add origin_xyz git@github.com:simpliwp/xyz.git
#push the branch to the empty repo's master branch
git push origin_xyz XYZ:master
将新创建的远程仓库克隆到新的本地目录中
#change current directory out of the old repo
cd /path/to/where/you/want/the/new/local/repo
#clone the remote repo you just pushed to
git clone git@github.com:simpliwp/xyz.git
git clone git@example.com:thing.git
cd thing
git fetch
for originBranch in `git branch -r | grep -v master`; do
branch=${originBranch:7:${#originBranch}}
git checkout $branch
done
git checkout master
git filter-branch --index-filter 'git rm --cached -qr --ignore-unmatch -- . && git reset -q $GIT_COMMIT -- dir1 dir2 .gitignore' --prune-empty -- --all
git remote set-url origin git@example.com:newthing.git
git push --all
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
36326 次 |
| 最近记录: |