我想重命名/移动Git中的项目子树
/project/xyz
to
/components/xyz
如果我使用普通的gitmv项目组件,那么xyz项目的所有提交历史都会丢失。有没有一种方法可以移动它,以保持历史?
我想重命名/移动Git中的项目子树
/project/xyz
to
/components/xyz
如果我使用普通的gitmv项目组件,那么xyz项目的所有提交历史都会丢失。有没有一种方法可以移动它,以保持历史?
当前回答
git log --follow [file]
将通过重命名向您展示历史。
其他回答
我曾面临“重命名文件夹而不丢失历史记录”的问题。要修复此问题,请运行:
$ git mv oldfolder temp && git mv temp newfolder
$ git commit
$ git push
我遵循这个多步骤过程将代码移动到父目录并保留历史记录。
步骤0:从“master”创建了分支“history”以进行安全保管
步骤1:使用gitfilter repo工具重写历史。下面的命令将文件夹“FolderwithContentOfInterest”移动到一个级别,并修改了相关的提交历史记录
git filter-repo --path-rename ParentFolder/FolderwithContentOfInterest/:FolderwithContentOfInterest/ --force
步骤2:此时GitHub存储库丢失了远程存储库路径。添加远程引用
git remote add origin git@github.com:MyCompany/MyRepo.git
步骤3:从存储库中提取信息
git pull
步骤4:将本地丢失分支连接到源分支
git branch --set-upstream-to=origin/history history
步骤5:如果提示,解决文件夹结构的合并冲突
第6步:推!!
git push
注意:修改的历史记录和移动的文件夹似乎已提交。在此处输入代码
完成。代码移动到父目录/所需目录,保持历史记录完整!
我愿意:
git mv {old} {new}
git add -u {new}
要重命名目录或文件(我不太了解复杂的情况,因此可能需要注意):
git filter-repo --path-rename OLD_NAME:NEW_NAME
要在提到目录的文件中重命名目录(可以使用回调,但我不知道如何):
git filter-repo --replace-text expressions.txt
expressions.txt是一个充满了文字:OLD_NAME==>NEW_NAME等行的文件(可以将Python的RE与regex一起使用,也可以将glob与glob一起使用)。
要重命名提交消息中的目录,请执行以下操作:
git-filter-repo --message-callback 'return message.replace(b"OLD_NAME", b"NEW_NAME")'
Python的正则表达式也受支持,但必须用Python手动编写。
如果存储库是原始的,没有远程,则必须添加--force以强制重写。(在执行此操作之前,您可能需要创建存储库的备份。)
如果不想保留引用(它们将显示在GitGUI的分支历史记录中),则必须添加--replace-refs delete no add。
我想重命名/移动Git中的项目子树/项目/xyz到/组件/xyz如果我使用普通的gitmv项目组件,那么xyz项目的所有提交历史都会丢失。
没有(8年后,Git 2.19,2018年第3季度),因为Git会检测到目录重命名,现在已经有了更好的记录。
参见Elijah Newren(Newren)提交的提交b00bf1c、提交1634688、提交0661e49、提交4d34dff、提交983f464、提交c840e1a、提交9929430(2018年6月27日)和提交d4e8062、提交5dacd4a(2018年7月25日)。(于2018年7月24日由Junio C Hamano(吉斯特)在提交时合并)
现在在Documentation/technical/directory-rename-detection.txt中对此进行了解释:
例子:
当所有x/a、x/b和x/c都移动到z/a、z/b和z/c时,很可能同时添加的x/d也希望通过以下方式移动到z/d提示整个目录“x”移动到“z”。
但还有很多其他情况,比如:
历史的一方重命名为x->z,另一方将某个文件重命名为x/e,导致合并需要进行传递重命名。
为了简化目录重命名检测,这些规则由Git强制执行:
当应用目录重命名检测:
如果合并的两边仍然存在给定的目录,我们不认为它已被重命名。如果要重命名的文件的子集有一个文件或目录在其中(或将相互妨碍),请“关闭”这些特定子路径的目录重命名,并向用户报告冲突。如果历史的另一端将目录重命名为您的历史的另一侧重命名的路径,那么对于任何隐式目录重命名,忽略历史另一端的特定重命名(但警告用户)。
您可以在t/t6043-merge-rename-directories.sh中看到许多测试,其中还指出:
a) 如果重命名将一个目录拆分为两个或多个其他目录,则重命名最多的目录“获胜”。b) 避免对路径进行目录重命名检测,如果该路径是合并两侧重命名的源。c) 仅在另一侧对目录应用隐式目录重命名历史是一个做更名的人。