我想重命名/移动Git中的项目子树
/project/xyz
to
/components/xyz
如果我使用普通的gitmv项目组件,那么xyz项目的所有提交历史都会丢失。有没有一种方法可以移动它,以保持历史?
我想重命名/移动Git中的项目子树
/project/xyz
to
/components/xyz
如果我使用普通的gitmv项目组件,那么xyz项目的所有提交历史都会丢失。有没有一种方法可以移动它,以保持历史?
当前回答
首先,只需重命名即可创建独立提交。
然后,对文件内容的任何最终更改都将放在单独的提交中。
其他回答
No.
简短的答案是否定的。在Git中重命名文件并记住历史是不可能的。这是一种痛苦。
有传言说,git log--follow--查找副本会更加困难,但这对我来说不起作用,即使文件内容没有任何更改,而且这些移动都是用git mv完成的。
(最初,我使用Eclipse在一次操作中重命名和更新包,这可能会混淆Git。但这是一件非常常见的事情。--如果只执行mv,然后提交mv,并且mv不太远,那么follow似乎确实有效。)
Linus表示,您应该全面了解软件项目的全部内容,而不需要跟踪单个文件。不幸的是,我的小脑袋无法做到这一点。
这么多人无意识地重复了Git自动跟踪移动的说法,这真的很烦人。他们浪费了我的时间。Git没有这样做。根据设计(!)Git根本不跟踪移动。
我的解决方案是将文件重命名回其原始位置。更改软件以适合源代码管理。使用Git,您似乎只需要第一次“获取”它。
不幸的是,这打破了Eclipse,它似乎使用了--follow。gitlog--follow有时不会显示具有复杂重命名历史的文件的完整历史记录,尽管gitlog会显示。(我不知道为什么。)
(有一些过于聪明的黑客会重新开始旧的工作,但它们相当可怕。请参阅GitHub Gist:emiller/git mv with history。)
简而言之:如果Subversion这样做是错误的,那么Git这样做也是错误的——这样做不是什么(错误!)功能,这是错误的。
可以重命名文件并保持历史记录不变,尽管这会导致文件在存储库的整个历史记录中被重命名。这可能只适用于痴迷于git日志的爱好者,并有一些严重的影响,包括:
您可以重写共享历史,这是使用Git时最重要的“不要”。如果其他人克隆了存储库,您将通过此操作将其破坏。他们将不得不重新克隆以避免头痛。如果重命名足够重要,这可能是可以的,但您需要仔细考虑这一点——您可能会扰乱整个开源社区!如果您在存储库历史记录的早期使用文件的旧名称引用了该文件,那么实际上就是在破坏早期版本。为了解决这个问题,你必须多跳一点环跳。这不是不可能的,只是乏味而且可能不值得。
现在,既然你还和我在一起,你可能是一个单独的开发人员,正在重命名一个完全独立的文件。让我们使用过滤器树移动文件!
假设您要将一个旧文件移动到文件夹目录中,并将其命名为new
这可以用git-mv-old-dir/new&&git-add-u-dir/new来完成,但这打破了历史。
相反:
git filter-branch --tree-filter 'if [ -f old ]; then mkdir dir && mv old dir/new; fi' HEAD
将重做分支中的每个提交,在每个迭代的滴答声中执行命令。当你这样做的时候,很多事情都会出错。我通常会测试文件是否存在(否则它还没有移动),然后执行必要的步骤,按照我的喜好强行插入树。在这里,您可能会浏览文件以更改对文件的引用等等
完成后,文件将被移动,日志将完好无损。你觉得自己像忍者海盗。
而且当然,只有当您将文件移动到新文件夹时,mkdir目录才是必需的。if将避免在文件存在之前创建此文件夹。
我遵循这个多步骤过程将代码移动到父目录并保留历史记录。
步骤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
注意:修改的历史记录和移动的文件夹似乎已提交。在此处输入代码
完成。代码移动到父目录/所需目录,保持历史记录完整!
在我的例子中,我将两个文件从“resources”目录移动到“src/main/resources”。如下代码所示,它们显示为“已删除”。
然而,在我将重新定位的文件添加到临时区域,然后添加删除的文件后,系统将它们识别为“重命名”。
当我检查这两个文件的历史记录时,它是完整的,它们的永久链接仍然有效。所以,一切都如我们所愿。
myaddress (master *)$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: resources/myaddress-schemas.sql
deleted: resources/select-sangdo-ro-60.sql
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
pom.xml
src/
myaddress (master *)$ git add src/main/resources/*.sql
myaddress (master *+)$ git add `git ls-files --deleted`
myaddress (master +)$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: resources/myaddress-schemas.sql -> src/main/resources/myaddress-schemas.sql
renamed: resources/select-sangdo-ro-60.sql -> src/main/resources/select-sangdo-ro-60.sql
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
pom.xml
src/main/java/
src/main/webapp/
myaddress (master +)$
myaddress (master +)$ git commit -m "two resource files moved to src/main"
[master 0832839] two resource files moved to src/main
2 files changed, 0 insertions(+), 0 deletions(-)
rename {resources => src/main/resources}/myaddress-schemas.sql (100%)
rename {resources => src/main/resources}/select-sangdo-ro-60.sql (100%)
myaddress (master)$
我愿意:
git mv {old} {new}
git add -u {new}