我已经创建了新仓库,并将旧仓库从文件系统作为“remote”添加,创建了一个新的“根提交”(只是为新的单文件项目添加了一个README)。现在我需要将与该特定文件相关的提交移植到新的根提交上。
(我应该提到,在同一次提交中未修改此文件和其他任何文件;我认为这可能会使这个任务稍微容易些。)
以下内容基于filter-branch手册中的一个示例:
git filter-branch --index-filter 'git ls-files -s | grep $'\t'<file-to-keep>$ | \
GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && \
mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' --prune-empty -- --all
git ls-files -s
打印索引的当前内容,仅保留要保留的文件(grep非常强迫症——字段是以制表符分隔的,文件名是最后一个字段),然后使用该信息创建一个新索引,并将其移动到旧索引之上。
--prune-empty
选项会导致filter-branch删除任何现在没有作用的提交(即它们只更改了其他文件),而-- --all
则告诉它重写所有引用。git rm --cached --ignore-unmatch <filename>
进行索引过滤器即可。)Rewrite bb6a446cc395e38cdcb7af7953b151e0a706929d (1/15)mv: /Users/elliottcable/Code/Cest.c/.git-rewrite/t/../index.new: No such file or directory
- ELLIOTTCABLE另一种解决方案是将旧存储库添加为另一个远程存储库,然后进行变基和挑选操作。
git clone old_repo
git clone new_repo
cd new_repo
git remote add temp_repo old_repo
git fetch temp_repo
# bring the changed from old_repo into new_repo
git rebase --onto <...> temp_repo/master
OR
git cherry-pick [list of relevant commits]
git remote rm temp_repo
git push origin HEAD
我最终使用了这个(本来与此无关的)帖子中的回答来构建解决方案。我没有将提交记录变基到一个新的树中,而是修改了旧的根,并使用--onto
参数将内容变基到新的根:
在尝试了各种方法将文件或文件夹从一个Git存储库移动到另一个存储库后,唯一可靠的方法是以下步骤:
首先克隆您想要移动文件或文件夹的存储库,将该文件或文件夹移动到根目录,重写Git历史记录,然后克隆目标存储库并直接将带有历史记录的文件或文件夹拉入此目标存储库。
将仓库A复制一份,因为以下步骤会对此副本进行重大更改,您不应该推送!
git clone --branch <branch> --origin origin --progress -v <git repository A url>
例如:git clone --branch master --origin origin --progress -v https://username@giturl/scm/projects/myprojects.git
(假设myprojects是您要从中复制的存储库)
进入该目录
cd <git repository A directory> 例如:cd /c/Working/GIT/myprojects
删除与原始存储库的链接,以避免意外地进行任何远程更改(例如通过推送)
git remote rm origin
浏览您的历史记录和文件,删除不在目录1中的任何内容。结果是将目录1的内容排出到存储库A的基础目录中。
git filter-branch --subdirectory-filter <directory> -- --all
例如:git filter-branch --subdirectory-filter subfolder1/subfolder2/FOLDER_TO_KEEP -- --all
仅适用于单个文件移动:浏览剩下的内容并删除除所需文件以外的所有内容。(您可能需要删除名称相同的不想要的文件并提交。)
git filter-branch -f --index-filter \
'git ls-files -s | grep $'\t'FILE_TO_KEEP$ |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info && \
mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE || echo "Nothing to do"' --prune-empty -- --all
例如:FILE_TO_KEEP = pom.xml,以仅保留FOLDER_TO_KEEP中的pom.xml文件。
第二阶段
清理步骤
git reset --hard
清理步骤
git gc --aggressive
清理步骤
git prune
您可能想将这些文件导入到存储库B中的一个目录而不是根目录:
创建该目录
mkdir <base directory> 例如:mkdir FOLDER_TO_KEEP
将文件移动到该目录中
git mv * <base directory> 例如:git mv * FOLDER_TO_KEEP
将文件添加到该目录中
git add .
提交您的更改,我们准备将这些文件合并到新存储库中
git commit
第三阶段
如果您还没有B存储库的副本,请制作一个
git clone <git repository B url>
例如:git clone https://username@giturl/scm/projects/FOLDER_TO_KEEP.git
(假设FOLDER_TO_KEEP是您要复制到的新存储库的名称)
进入该目录
cd <git repository B directory> 例如:cd /c/Working/GIT/FOLDER_TO_KEEP
在存储库B中创建一个远程连接,作为存储库A中的一个分支
git remote add repo-A-branch <git repository A directory>
(repo-A-branch可以是任何东西 - 它只是一个任意的名称)
例如:git remote add repo-A-branch /c/Working/GIT/myprojects
从此分支(仅包含要移动的目录)拉取到存储库B中。
git pull repo-A-branch master
拉取操作会同时复制文件和历史记录。注意:您可以使用合并而不是拉取,但拉取效果更好。
最后,您可能想要清理一下,删除与存储库A的远程连接
git remote rm repo-A-branch
推送并完成。
git push