首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在保留子目录的同时拆分git存储库?

如何在保留子目录的同时拆分git存储库?
EN

Stack Overflow用户
提问于 2010-05-09 17:30:47
回答 5查看 6.2K关注 0票数 21

我想要的类似于this question。但是,我希望拆分成单独存储库的目录仍然是该存储库中的一个子目录:

我有这个:

代码语言:javascript
复制
foo/
  .git/
  bar/
  baz/
  qux/

我想把它分成两个完全独立的存储库:

代码语言:javascript
复制
foo/
  .git/
  bar/
  baz/

quux/
  .git/
  qux/  # Note: still a subdirectory

如何在git中做到这一点?

如果有某种方法可以将所有新存储库的内容移到一个子目录中,那么我可以使用this answer中的方法。

EN

回答 5

Stack Overflow用户

发布于 2011-11-01 21:01:57

这就是当我自己解决这个问题时,我最终做的事情:

代码语言:javascript
复制
git filter-branch --index-filter \
'git ls-tree --name-only --full-tree $GIT_COMMIT | \
 grep -v "^directory-to-keep$" | \
 sed -e "s/^/\"/g" -e "s/$/\"/g" | \
 xargs git rm --cached -r -f --ignore-unmatch \
' \
--prune-empty -- --all

这个解决方案是基于Jefromi的回答和Detach (move) subdirectory into separate Git repository,再加上很多关于SO的评论。

Jefromi的解决方案对我不起作用的原因是,我的存储库中有文件和文件夹的名称包含特殊字符(主要是空格)。此外,git rm还抱怨不匹配的文件(使用--ignore-unmatch解决)。

您可以保持过滤对不在存储库的根目录中或被四处移动的目录的不可知性:

代码语言:javascript
复制
grep --invert-match "^.*directory-to-keep$"

最后,您可以使用它来筛选出文件或目录的固定子集:

代码语言:javascript
复制
egrep --invert-match "^(.*file-or-directory-to-keep-1$|.*file-or-directory-to-keep-2$|…)"

要在之后进行清理,可以使用以下命令:

代码语言:javascript
复制
$ git reset --hard
$ git show-ref refs/original/* --hash | xargs -n 1 git update-ref -d
$ git reflog expire --expire=now --all
$ git gc --aggressive --prune=now
票数 3
EN

Stack Overflow用户

发布于 2013-08-16 04:50:39

我想做类似的事情,但是因为我想保留的文件列表很长,所以使用无数grep来做这件事是没有意义的。我写了一个从文件中读取文件列表的脚本:

代码语言:javascript
复制
#!/bin/bash

# usage:
# git filter-branch --prune-empty --index-filter \
# 'this-script file-with-list-of-files-to-be-kept' -- --all

if [ -z $1 ]; then
    echo "Too few arguments."
    echo "Please specify an absolute path to the file"
    echo "which contains the list of files that should"
    echo "remain in the repository after filtering."
    exit 1
fi

# save a list of files present in the commit
# which is currently being modified.
git ls-tree -r --name-only --full-tree $GIT_COMMIT > files.txt

# delete all files that shouldn't be removed
while read string; do
    grep -v "$string" files.txt > files.txt.temp
    mv -f files.txt.temp files.txt
done < $1

# remove unwanted files (i.e. everything that remained in the list).
# warning: 'git rm' will exit with non-zero status if it gets
# an invalid (non-existent) filename OR if it gets no arguments.
# If something exits with non-zero status, filter-branch will abort.
# That's why we have to check carefully what is passed to git rm.
if [ "$(cat files.txt)" != "" ]; then
    cat files.txt | \
    # enclose filenames in "" in case they contain spaces
    sed -e 's/^/"/g' -e 's/$/"/g' | \
    xargs git rm --cached --quiet
fi

令人惊讶的是,这项工作比我最初预期的要多得多,所以我决定把它贴在这里。

票数 3
EN

Stack Overflow用户

发布于 2016-05-21 00:05:17

一种更干净的方法:

代码语言:javascript
复制
git filter-branch --index-filter '
                git read-tree --empty
                git reset $GIT_COMMIT path/to/dir
        ' \
        -- --all -- path/to/dir

或者只使用核心命令,在git read-tree --prefix=path/to/dir/ $GIT_COMMIT:path/to/dir中执行重置。

在rev-list args上指定path/to/dir可以提前进行修剪,使用这么便宜的过滤器并不重要,但无论如何都可以避免浪费精力。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2797191

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档