【问题标题】:Git wrongly mark a file as deleted instead of rewritten [duplicate]Git错误地将文件标记为已删除而不是重写[重复]
【发布时间】:2020-05-30 11:01:55
【问题描述】:

我正在对一个项目进行多次重构。所以有时我需要重命名文件扩展名,例如index.js -> index.ts,并在这个文件上更改很多行。

因为 git 错误地将 index.js 标记为已删除,并将 index.ts 标记为新文件,这可能对代码审查和日志不利。

有什么方法可以明确地对 git 说“嘿,我将 index.js 重命名为 index.ts”?

编辑

使用git add / git rm / git mv的方法不起作用,因为git仍然说我创建了一个新文件并删除了其他文件。

我也不应该使用两次提交(一个用于重命名,一个用于更新其内容),因为第一次提交将被破坏,因为.js 文件的构建步骤与.ts 文件不同

【问题讨论】:

  • 是的。吉特移动。 --- 你修改了多少文件内容?
  • @evolutionxbox 我尝试使用此命令,但收到错误消息:fatal: bad source, source=front/src/index.jsx, destination=front/src/index.tsx
  • 而且我在这个文件上更改了很多行,足以让 git 无法自动检测到我刚刚重命名了这个文件。
  • @MarekR Nop,因为 git 无法自动检测到,因为我更改了很多行
  • 基本上Do the move and the modify in separate commits. 就完成了。

标签: git


【解决方案1】:

Git 通常会注意到您是否移动了文件,如果您没有过多地处理文件的内部结构。无论哪种方式,这是一种不好的做法,您应该努力始终使用 git 本身明确地移动文件。

git mv index.js index.ts

通常我强烈希望将移动和文件更改作为单独的提交完成。

如果在这方面已经造成损害......复制您已更改的文件并恢复回购可能会有所帮助。然后您可以重命名文件,并在其上复制更改。

【讨论】:

  • 嗯...我不能只提交将index.js 重命名为index.ts,因为无法构建这个新文件
  • @Macabeus:如果您对可以和不可以提交到版本控制的内容的限制是可以构建的内容,那么您使用的版本控制是错误的。
  • @Macabeus:我知道受保护的主分支可能就是这种情况,但这是分支的工作类型。
  • 不,我没有使用master 分支。我正在使用另一个分支,我可以重写它的历史。无论如何,我试图创建一个新的提交,只是重命名文件并修改更改,但它没有用。提交说“index.js 已删除,index.ts 已添加”
【解决方案2】:

不,在 git 中没有办法将文件显式标记为已移动。

git mv ... 的作用与git rm ...; git add ... 相同。

如果对文件的更改不是太大,Git 将自动检测删除并添加到同一个提交中。您可以使用 -M 选项为某些命令 git log 指定“相似度索引”。将其设置得较低,例如-M30% 表示新旧文件中只有 30% 的行必须匹配,文件才会被视为重命名。

这只是 git 要习惯的功能之一。见:

How to make git mark a deleted and a new file as a file move?

How to REALLY show logs of renamed files with git? 等等

【讨论】:

    【解决方案3】:

    有什么方法可以明确地对 git 说“嘿,我将 index.js 重命名为 index.ts”?

    没有。

    仅此而已。 Git 不存储对文件的更改。 Git 存储文件的快照。在快照 X 中,您有一个名为 index.js 的文件。在快照 Y 中,您有一个名为 index.ts 的文件。

    在比较快照 X 和快照 Y 时,您可以让 Git 检测重命名。检测基于两个事实:

    1. 在快照 X 中,有一个名为 index.js 的文件,而在快照 Y 中,该文件不存在,但确实存在一个名为 index.ts 的新文件;因此可以将这两个名称放入候选列表中进行重命名检测。

    2. 现在重命名检测的候选列表中填满了从左侧 (X) 提交中消失并出现在右侧 (Y) 提交中的所有文件名,Git 将比较每对文件。如果这两个文件的内容足够相似,Git 将暂时配对该对,记住这个 similarity index 值。遍历所有可能的配对后,Git 将采用具有 best 相似性索引的配对,并将该文件称为“重命名”。

    当你让 Git 比较快照 X 和 Y 时——对于任何提交哈希 XY,真的——要告诉 Git:

    1. 使用或不使用重命名检测器;
    2. 如果使用重命名检测器,临时配对文件的最小相似度阈值是多少?

    使用git diff 命令,重命名检测器在 Git 2.9 之前默认为 off,在 Git 2.9 及更高版本中默认为 on相似度阈值值在所有版本的 Git 中默认为“50% 相似度”。使用-M 标志打开检测器并设置相似度阈值。

    当使用其他 Git 命令时,其他标志和参数可能允许您启用重命名检测并设置阈值——或者在某些情况下,不能这么多。例如,git log --follow 打开重命名检测器,但将其限制为仅一个文件名,并且不允许您设置阈值。

    git status 命令用于始终启用重命名检测并将阈值设置为 50%。它现在遵循git config 设置来启用或禁用重命名检测,但仍然无法设置阈值。

    同样,当您比较两个提交时,会发生这种重命名检测。提交本身只是所有文件的快照。两个不同的git diff 命令,具有不同的重命名检测设置,将显示不同的操作集,从而将第一个提交替换为第二个提交。 git diff 命令不显示某人实际做了什么。相反,它显示了一些将产生相同结果的操作序列。

    【讨论】:

    • 谢谢。我有点不高兴,因为那。能够添加快照可能会很有用“嘿,我重命名了这个文件,忽略这种情况下的阈值”。
    • @Macabeus:这将有助于父/子交叉,但在比较祖父母和孙子时不会有任何好处(Git 不会查看介入的提交)。无论如何,目前没有地方放这些东西,也没有计划添加我见过的东西。
    • 我向 git 的邮件列表发送了一封电子邮件,其中包含以下建议:lore.kernel.org/git/…
    猜你喜欢
    • 2014-12-07
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    • 2016-08-18
    • 1970-01-01
    • 1970-01-01
    • 2020-06-22
    • 1970-01-01
    相关资源
    最近更新 更多