【问题标题】:Move file to separate repository without moving file on disk将文件移动到单独的存储库而不移动磁盘上的文件
【发布时间】:2017-06-26 03:10:54
【问题描述】:

此问题与How to move files from one git repo to another (not a clone), preserving history 等有关 Detach (move) subdirectory into separate Git repository 但问题(或者至少是解决方案,我认为)是不同的。我有以下目录结构:

abc/
    .git/
    def/
       file1.txt
       file2.txt
    xyz/
       file3.txt

abc 目录是 git 存储库的根目录,例如 repo1

我想要的是将file2.txt 放在不同的存储库中,repo2(本地并链接到远程)。但是,我不想将file2.txt 移出目录(如相关问题中所述)。所有其他文件和文件夹 (def, file1.txt, xyz/*) 必须保留在 repo1

当我执行git commitgit push 时,对file1.txt 的更改应该转到repo1,对file2.txt 的更改应该转到repo2

作为一种解决方法,我可以在def 中创建一个附加目录并将file2.txt 移动到那里,如果这样更容易的话。但是,我不想将file2.txt 移出当前树。

file2.txt的历史不一定需要在这次搬家中保留。

【问题讨论】:

  • 我所知道的最接近你想要的东西是使用一个包含file2.txt的子模块。

标签: git repository-design


【解决方案1】:

首先,确保您提交或存储任何更改并且您的工作树是干净的。运行git status 确定。

只需两个简单的步骤即可实现您的目标。

  1. abc/def 中创建一个新的空仓库。将其配置为忽略除file2.txt 之外的所有文件(您希望以与file2.txt 相同的方式处理的任何其他文件)。将 .gitignorefile2.txt 添加到新的仓库并提交:

    $ cd abc/def
    $ git init
    $ echo '*' > .gitignore
    $ echo '!/file2.txt' >> .gitignore
    $ git add .
    $ git status
    $ git commit
    

    仔细阅读git status 的输出并确认它仅将所需的文件添加到存储库中。如果一切正常,请提交或调整 .gitignore 和索引,直到它们达到您需要的状态。

  2. 转到abc repo,将def/file2.txtdef/.gitignore 添加到此repo 的忽略列表中,从索引中删除def/file2.txt 并提交:

    $ cd ..
    $ echo '/def/file2.txt' >> .gitignore
    $ echo '/def/.gitignore' >> .gitignore
    $ git rm --cached def/file2.txt
    $ git status
    $ git commit
    

    同样,在提交之前阅读git status 的输出。

备注

您可以像往常一样使用这两个存储库。它们是独立的,它们没有以任何方式链接(除了每个 repo 都配置为忽略另一个 repo 管理的文件这一事实)。

如果您不将内部存储库推送到远程位置,我建议您将其.git 目录(存储库本身)移动到abc 目录之外的某个位置,以防止其意外删除。命令很简单。在abc/def 目录内运行:

git init --separate-git-dir=/path-where-to-move-the-git-dir

您可以在创建 abc/def 存储库时运行此命令行,也可以在此之后运行它。回购中包含的数据是安全的。它只会将 repo 移动到指定的位置。

【讨论】:

  • 很好,我不知道在单独的目录中创建存储库的选项。我注意到它正在创建一个文件.git,其中包含实际 git 目录的路径。这个文件是否也需要被“主机”存储库忽略,如.gitignorefile2.txt,还是需要特殊处理?
  • 工作就像一个魅力,谢谢!我想我重命名文件时必须手动更改.gitignores?
  • " 我注意到它正在创建一个 .git 文件,其中包含实际 git 目录的路径。" -- documentation of git init 也是这么说的。我还没有找到官方参考,但似乎 Git 知道工作树中名为 .git 的文件或文件夹使其父目录成为 Git 存储库,并且它忽略了 .git 文件或目录而没有被告知。 submodules 的 Git 处理也使用了这种技术。
  • 确实,如果要重命名文件,则必须更改两个 .gitignore 文件。请记住,文件abc/.gitignore 告诉外部存储库要忽略哪些文件,文件abc/def/.gitignore 告诉内部存储库忽略哪些文件。
  • 或者,您可以将file2.txt 的名称放在.git/info/exclude(而不是.gitignore)中的一个或两个repos 中。优点是,如果您在内部存储库中添加/删除/重命名文件,则无需再更改和提交 .gitignore。缺点是 .git/info/exclude 是 repo 本地的。它不能被推送到远程存储库。
猜你喜欢
  • 2019-02-11
  • 2010-10-30
  • 2018-05-15
  • 1970-01-01
  • 2020-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多