之前我曾问过类似的问题,但在对此事进行了相当彻底的分析后得出的结论是git filter-branch
是我正在寻找的主力。在.git
本身中执行脏工作的那个或shell脚本(因为git无论如何都将其内容暴露为其接口的一部分)。
我有一个项目目录,其中包含构建脚本和构建配置定义。更重要的是,它包含src
文件夹,其中包含项目的各种源代码,是一个git存储库。
我现在意识到整个项目文件夹应该是一个git存储库,而不仅仅是包含的源代码文件夹,但我希望保留源代码开发的历史记录。实际上,我希望历史记录完全重写,以便跟踪名为main.c
的文件中的更改,而不是跟踪文件src/main.c
中的相同内容更改。然后我可以简单地从父文件夹(构建脚本所在的位置)移动文件,并在repo中检查它们。
我不想打扰子树合并或git子模块,或者在更改存储库后必须合并或重置任何内容。我现在对gits内部有一些相当好的了解 - 提交引用了引用与文件名配对的blob的树。
有了这些知识,我认为应该可以重写我的历史记录,为所有路径添加前缀src/
我只是不想做额外的工作,似乎filter-branch
是要走的路,但是在使用它之后我会混淆示例和必要的内务管理。 “原始参考”?另一个问题是我完全没有“裸”回购,我不需要任何工作树,我也不确定为什么我需要索引。
答案 0 :(得分:3)
这并不像你想象的那么简单。您目前有两个存储库,每个存储库都有自己的历史记录 每个提交都有一个明确定义的父级。
要获得单个,按时间顺序排列的正确历史记录,您必须更改许多提交的父级。
一个简短的例子说明了这一点:
存储库“配置”:
A <- C <- E
存储库“src”
B <- D <- F
让我们假设提交B发生在B等之后的A和C之后,所以你想得到这个结果:
A <- B' <- C' <- D' <- E' <- F'
要实现此目的,您必须将B'
的父级更改为A
。 C'
的父级必须从A
更改为B'
等。
这不是微不足道的。但可能。
假设配置存储库位于“/ usr / git / config”,src存储库位于“/ usr / git / config / src”。
首先,我们必须准备“src”存储库以包含“src”子文件夹中的所有文件:
执行这个怪物:
git filter-branch --index-filter 'git ls-files -s | sed "s-\t\"*-&src/-" | GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
其余的将在“config”存储库中发生,因此CD为“/ usr / git / config”。
git remote add src /usr/git/config/src
git fetch src
git merge src/master master
git rev-list --max-parents=0 --pretty HEAD
git rebase -f <hash from step 5>
git remote remove src
请注意:
这假设您在两个存储库中只有一个主分支。
哦,并且请在执行此操作之前进行备份。我只在一个小型测试存储库上测试了它,每个提交两次...
如果你在src子文件夹中只有一个存储库,那就更简单了,只需执行以下命令: