重构 Git 仓库

3

I have a git repo structure like this-

main-repo
  -file1
  -file2

我希望将其转换为类似于以下内容的东西-
main-repo
   -javascript
       -file1
       -file2

然后稍后可以添加另一个不同语言的存储库,例如

main-repo
    -javascript
        -file1
        -file2
    -python
        -file1
        -file2

如果我已经有了几个提交且在travis.yml中配置了测试来在推送到主分支时运行,那么如何做到这一点。

2个回答

3
我有一个像这样的git仓库结构-... 我想把它转换成像这样的东西-...
将文件移动到存储库中没有任何问题。但是,即使Git可能会自动检测文件移动(因为某些文件会消失,其他一些文件会出现,并且具有完全相同的内容),但还是有专门的命令来执行此操作:
git mv <source> <destination>

文件将自动移动,并且在 git status 的报告中会显示这一操作。因此,您需要提交以记录此更改。
始终进行提交是一个好习惯,因为我们应该尽量避免在 git 存储库中重命名/移动文件,除非确实有必要。这是因为这些给定文件的历史连续性将被打破,使它们难以追溯。
每个提交都应该是独立的,即使每个提交都涉及之前的提交(或合并时的多个提交)。它们基本上是一个完全限定的文件名称列表,每个文件名称指向其各自的内容,这使您可以轻松比较任何两个提交(使用 git diff),无论它们在图形中的位置如何。
这真的很强大,但缺点是 Git 依赖于文件名来知道要比较什么。如果提交和下一个提交之间只有少量名称更改,Git 将猜测它们实际上是哪些。但是,如果您同时引入文件更改和重命名,或者如果您重命名一个文件并创建另一个具有相同内容的文件,则 Git 将感到困惑。
通过使用 git mv,您为 Git 提供了存储每个所需信息以帮助完成此任务的机会。此外,在一些其他工作方式不同的 SCM 中,这可能是强制性的。

然后稍后在另一种语言中添加另一个仓库

这没有什么特别之处。只需像开始时那样添加额外的内容(但不要忘记提交),但请注意 Git 无法处理空目录。因此,您需要在 "python" 目录中至少添加一个文件。这也意味着,一旦您删除了给定目录中的最后一个文件,该目录本身也将在下次检出时自动消失。不要对此感到惊讶。
这是由于如前所述,Git 只考虑文件(即使它仍能够处理符号链接和特殊文件),并通过维护完全限定文件名称(例如 "/dirname/basename")来跟踪它们各自的位置。因此,它不能处理末端没有叶子的分支。
另外,如果您的 "javascript" 和 "python" 目录没有任何关联(它们不是同一个项目的一部分),最好将它们转换为多个独立的 git 存储库。请记住,即使其中已经有一些内容,您仍可以使用 git init 初始化新的存储库。
最后,当您达到想在较大的存储库中创建一个存储库的点时,例如在公开共享小存储库同时保留有关其的其他信息,或者在处理一个其库是一个独立项目的大型项目时,您将想要查看 git submodule,但今天不需要。 :)

2
最简单的方法是移动文件并提交一个新版本。这可能会或可能不会足够。一方面,当然你还没有关于要添加的Python文件的历史记录,因此这将为完整的历史记录腾出空间。另一方面,单个文件的早期历史记录可能不总是显示出您想要的方式(因为Git的文件移动处理虽然不差,但并非完美)。
另一种选择是重新编写存储库的历史记录,使其看起来像始终具有所需目录结构。您可以使用“git filter-branch”完成此操作。如果存储库比较小,则可以传递一个带有类似以下脚本的“--tree-filter”参数:
mkdir javascript
mv file1 file2 javascript

你可以使用 mv *.js javascript 或者其他合适的方式来完成操作。

这个操作通常比较慢,但对于只有“几个”提交记录的新仓库来说还是比较合理的。

更多详情请参考 git filter-branch 文档:https://git-scm.com/docs/git-filter-branch


主要仓库与其关联的发布标签是代码在 npm 上打包和发布时使用的。这些标签会保持不变吗?另外,如果我将同样的代码重新打包为适用于 Python 的 pypi,它能够维护独立的发布标签吗? - Shashi Kumar Raja
@ShashiKumarRaja - filter-branch有一个tag-filter参数,用于控制如何重写标签。通常情况下,--tag-filter cat可以实现通常所需的操作(将现有标签移动到重写的树中)。您可以随意为以后的操作打上标签,但是标签始终适用于某个对象,通常是一个提交 - 而提交是所有内容的快照。出于这个(和许多其他)原因,使用git在单个仓库中存储逻辑上分离的项目是不可取的。因此,如果这些项目足够独立,需要拥有各自的发布标签系列,我建议使用两个仓库。 - Mark Adelsberger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接