GIT修改基础/根文件夹

5

我是一个有用的助手,可以为您提供文本翻译。

我有一个历时约2年的存储库,有许多提交/分支,现在由于某些原因,我需要将存储库的根文件夹更改为上一级文件夹。

以下是一些示例,以澄清此概念。

我的存储库位于文件夹内:

c:\workspace\test\src\

我的仓库中有上述文件/子文件夹中所有更改的内容。

我想将这个代码仓库移动到:

c:\workspace\test

从现在开始,能够将所有更改添加到测试文件夹中,保留旧存储库历史记录。

因此,所有标记在文件夹"\"中的旧提交,现在应该检查在文件夹"\src"中。

对于旧提交,我可以或者不能有(这真的无关紧要)文件夹的实际内容。

这是否可能?

我希望我所解释的是可以理解的。

5个回答

3

我想你的意思是您的代码库的顶级目录是 c:\workspace\test\,而您希望 c:\workspace\test\src\ 成为新的顶级目录。首先,请检查是否符合此情况:

cd c:\workspace\test\src
git rev-parse --show-toplevel #print repo top-level directory

如果您的顶层目录确实是 c:\workspace\test\ ,则应该输出类似于此内容。如果是这样,您可以使用 git filter-branch 重新定位命令将"src"目录作为新的顶层目录。请注意,这是否真是您想要做的,因为它会破坏性地修改您的旧记录!任何影响此分支的提交都将被重新定位,以包含 src 文件夹作为新的顶层目录。请先备份当前分支。
cd c:\workspace\test\
git branch oldRoot #this backs up your current branch to a new branch called "oldRoot"    
git filter-branch --subdirectory-filter src HEAD #this modifies your history

警告!!! 请注意:

  1. 如果您将更改备份到远程,请注意新历史记录将无法干净地应用,您需要执行以下操作之一:
    1. 开始使用新的远程分支(更安全),或:
    2. 强制推送以覆盖远程历史记录。
  2. 如果其他人正在与您协作此repo,则他们可能会遇到麻烦。确保他们首先合并其更改,因为在您进行变基后对其进行合并将很困难。

有关更多信息,请阅读Git Book中的“将子目录设置为新根目录”和“变基的危险”部分。


0
git filter-branch --index-filter '
    git read-tree $(printf "040000 tree %s\tsrc\n" `git rev-parse HEAD:` | git mktree)
    ' -- --branches --tags
mv .git ..
cd ..

请查看这些命令的文档;它们的使用非常简单。filter-branch的文档中关于在tmpfs上让它执行其工作的建议可能值得考虑,因为需要处理两年的历史记录。

您可能想要执行grep -ri c.workspace.test .git以检查配置文件中是否有绝对路径,并验证它们是否仍然有效。


0

如果我正确理解了你的问题,如果你从一个干净的git仓库开始(git status显示“nothing to commit, working directory clean”),你只需要将c:\workspace\test\src\中的.git目录移动到c:\workspace\test\

然后你需要用新布局中的所有文件进行一次“大”的提交。Git会将这个新提交视为一个大的移动。不需要新内容,因为文件是相同的。Git只会在他的.git目录中注册新的树形布局(包括src)。


重新阅读问题让我想到,您可能希望在“src”子目录中使用旧的提交记录。
如果是这种情况,您需要使用类似于“git filter-branch --tree-filter '...'”这样的工具来完全重写Git存储库历史记录。

如果可能的话,我不想要一个新的“大”提交,而是想在存储库中将旧的根文件夹 \ 更改为新的 \src。但是我不知道是否可能。 - Marcx
我尝试过但没有成功,你能给我展示一下需要使用的命令的详细示例吗?谢谢。 - Marcx

0

听起来你只需要这样做:

  1. c:\workspace\test\src重命名为c:\workspace\src
  2. 删除目录c:\workspace\test,这个目录现在可能是空的
  3. c:\workspace\src重命名为c:\workspace\test

git仓库通常不会跟踪它们的父目录,因此将存储库从一个地方移动到另一个地方应该是无害的。现在,您在存储库中拥有的任何脚本/构建文件/任何可能包含硬编码路径的内容都可能是完全不同的故事...


不,我需要测试目录,并且在测试目录中有一些文件,从现在开始应该包含在git仓库中... - Marcx

0
首先,克隆您的存储库,以便您可以在隔离状态下进行工作,并且以防万一出现问题,使您的原始存储库保持完好无损。
git clone --no-hardlinks c:\workspace\test\src c:\sandbox

编写一个脚本,在任何单个提交时进行适当的更改。我不熟悉Windows脚本,但您需要编写一个脚本来创建一个名为src的新子目录(即c:\sandbox\src),然后将除.git目录和任何.git*文件(例如.gitignore)之外的所有内容移动到该新子目录中。确保您的脚本可以在存储库中的任何提交上正常工作,而不仅仅是在当前状态下运行。然后运行:

git filter-branch --tree-filter c:\absolute\path\to\your\script

这将导致git检出存储库中的每个提交,运行您的脚本,然后用最终结果替换提交。接下来,如果您有任何被忽略或未提交的文件,您需要将它们复制到新存储库中的适当位置。检查以确保filter-branch产生了预期的效果,并且新存储库看起来符合您的要求。一旦确定满意,删除c:\workspace\test,然后将c:\sandbox移动到c:\workspace\test

我更喜欢使用--tree-filter,如此处所示,而不是--index-filter。它不太高效(因为它必须检出每个提交而不是直接编辑索引),但我发现它更加直观。如果需要,它还可以让您更改存储库中文件的内容(例如更新绝对路径)。


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