简体   繁体   English

Git - 将文件标记为新文件而不是移动/复制

[英]Git - Mark file as new instead of moved/copied

Is there any way to force git to consider a file as new instead of moved/copied?有没有办法强制 git 将文件视为新文件而不是移动/复制?

Use case:用例:

  1. I have a large file, index.js我有一个大文件index.js
  2. I'm factoring out a small class from that file into Helper.js (only 10% of the index.js ) and renaming index.js to MyLib.js .我正在将该文件中的一个小类分解为Helper.js (仅index.js 10%)并将index.js重命名为MyLib.js MyLib.js will have some minor changes related to importing symbols from Helper.js . MyLib.js将有一些与从Helper.js导入符号相关的小改动。
  3. I need to recreate index.js as a new, 2-line file, that only re-exports symbols from Helper.js and MyLib.js .我需要将index.js重新创建为一个新的 2 行文件,该文件仅从Helper.jsMyLib.js重新导出符号。

I want the commit history to record renaming index.js to MyLib.js and treat the 2-line index.js as new, but git instead treats MyLib.js as completely new, and index.js as having lost 99% of its contents, down to only those 2 lines.我希望提交历史记录将index.js重命名为MyLib.js并将 2 行index.js视为新的,但 git 将MyLib.js视为全新的,而index.js已丢失其 99% 的内容,只有那两行。

The short answer is : no, git does not allow you to store information about how files were moved.简短的回答是:不, git不允许您存储有关文件如何移动的信息。

git tracks content , not diffs . git跟踪内容,而不是差异

When git displays the information :git显示信息时:

$ git diff --name-status HEAD^ HEAD
M    fileA          # fileA has been modified
R    oldB -> fileB  # fileB has been renamed
A    fileC          # fileC has been created

it actually has computed this information by comparing the contents of the two commits.它实际上是通过比较两次提交的内容来计算这些信息的。 It has not stored the information : "actually fileC was copied from fileA, and fileA was re-created as a new file".它没有存储信息:“实际上 fileC 是从 fileA 复制的,而 fileA 被重新创建为一个新文件”。

If two files have the same name in both commit, git diff will always compute "this file has been modified".如果两个文件在两个提交中具有相同的名称,则git diff将始终计算“此文件已被修改”。


Option 1 : keep the history you have, and live with it.选项 1:保留您拥有的历史,并与之共存。

Option 2 : you could try to do it in two commits选项 2:您可以尝试在两次提交中完成

  • create a first commit, where the only action is renaming file index.js to MyLib.js ,创建第一次提交,其中唯一的操作是将文件index.js重命名为MyLib.js

    • if you need the code to "work" -- for example so that unit tests or integration tests can be run on this commit -- update other modules so that they import MyLib.js instead of index.js如果您需要代码“工作”——例如,以便单元测试或集成测试可以在此提交上运行——更新其他模块,以便它们导入MyLib.js而不是index.js
  • create a second commit, where you apply the modifications you actually want to see创建第二次提交,在其中应用您实际想要查看的修改

    • extract a small class from MyLib.js to Helper.js ,MyLib.js提取一个MyLib.jsHelper.js
    • create a new index.js file with two lines and exported symbols,创建一个包含两行和导出符号的新index.js文件,
    • if you had modified the imports in the first commit, modify them again in this second commit.如果您在第一次提交中修改了导入,请在第二次提交中再次修改它们。

With option 2, some git commands ( git rebase , or git log --follow for example) would detect the renaming step in the repo's history, because they always inspect the history one commit at a time.使用选项 2,一些git命令(例如git rebasegit log --follow )将检测 repo 历史中的重命名步骤,因为它们总是一次检查一次提交的历史。

Some other commands, that do not look at a commit per commit diff but at a "global" diff, would still behave as option 1.其他一些命令,不查看每个提交差异的提交,而是查看“全局”差异,仍将作为选项 1。

For example : if you open a Merge Request (think github , gitlab , Azure Devops ...), the Merge Request interface would still present you with :例如:如果您打开一个合并请求(想想githubgitlabAzure Devops ...),合并请求界面仍然会向您显示:

  • file index.js has been modified,文件index.js已被修改,
  • file MyLib.js is an entirely new file文件MyLib.js是一个全新的文件

I am assuming that you used git mv to move that file, which is why Git is reporting it as having been moved.我假设您使用git mv移动该文件,这就是 Git 报告它已被移动的原因。 Something like this:像这样的东西:

git mv file.txt newfolder

But Git doesn't know what it can't see, so if you move the file from the filesystem Git will see the file in the new location as being new:但是 Git 不知道它看不到什么,所以如果你从文件系统中移动文件,Git 会看到新位置的文件是新的:

mv file.txt newfolder

You can git add this file to add it to the index.你可以git add这个文件将它添加到索引中。 After this, you could optionally delete the original the file from Git:在此之后,您可以选择从 Git 中删除原始文件:

git add newfolder/file.txt
git rm file.txt

Keep in mind that this means that Git won't be able to track the history of this file using this approach.请记住,这意味着 Git 将无法使用这种方法跟踪此文件的历史记录。 While using git mv also would make it difficult to track the history of the moved file, it would have at least made it somewhat possible.虽然使用git mv也会使跟踪移动文件的历史变得困难,但它至少在某种程度上使它成为可能。

Git is pretty smart figuring out when a file has been moved (if you delete the file and add it in the new location in the same commit, Git will figure out that the file has been moved). Git 非常聪明地确定文件何时被移动(如果您删除该文件并将其添加到同一提交中的新位置,Git 将确定该文件已被移动)。

If you actually want the file to be considered as "new" instead of "moved", probably the best option is to delete and add the file into its new location in separated commits.如果您确实希望将文件视为“新”而不是“已移动”,最好的选择可能是在单独的提交中删除文件并将其添加到其新位置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM