忽略 git 中重命名的文件夹

Ignore renamed folder in git

我有一个文件夹,比方说,

src/main/resources/basic_abc

为了运行本地化我的代码,我需要将它重命名为

src/main/resources/basic

这是我每次处理此存储库时都想执行的更改。我不希望 git 继续跟踪此文件夹并告诉我 basic_abc 已重命名为 basic。如何阻止 git 跟踪此重命名更改?

此外,如果我 运行 命令 git status,它确实会给出混乱的输出,因为此文件夹中有大量文件。

我该如何避免呢?

我认为这可以通过忽略“本地”目录来完成。

  • 创建一个新的“基本”目录
  • 将“basic_abc”中的所有内容复制进去
  • 转到项目目录中的 \.git\info,打开 exclude 文件。
  • 添加一个新行 src/main/resources/basic
  • 再次执行git status,您会看到git没有将新的“基本”目录视为未跟踪文件。但需要手动将其内容与“basic_abc”目录同步。只要在远程存储库中没有名为“basic”的目录或文件,就可以了。

exclude 文件用于“本地 git 忽略”。它的格式与 .gitignore 文件相同,但只适用于您的机器。

告诉 Git 忽略 basic_abc/ 已经消失了

警告 此解决方案仅在您不更改沙箱中的分支时才有效。跳到此答案的末尾以获取详细信息。 结束警告

您可以使用 git update-index --skip-worktree <file> 告诉 Git 忽略您在本地对文件所做的更改,这样 git status 和所有其他命令都会将其视为未更改。

我测试过,这也适用于已删除的文件。我没有找到对整个目录执行此操作的方法,但在 bash 命令行上编写脚本并不难。

一个文件:

git update-index --skip-worktree basic_abc/file1

basic_abc/中的所有文件:

git status --porcelain |
   grep " D src/main/resources/basic_abc" |
   sed "s/^ D //" |
   xargs git update-index --skip-worktree

解释:

  • git status 是 运行 和 --porcelain 所以你有稳定的 machine-readable 输出。
  • 如果需要,修复 grep 表达式,使其准确找到您希望 Git 假装不是 deleted/moved 的文件。
  • sed 命令只保留文件名。
  • 并且 xargs 对该管道的结果调用 git update-index --skip-worktree

让Git忽略basic/已经出现

正如@EddieDeng 所说,您可以使用 .git/info/exclude.gitignore 来完成此操作,请参阅他的回答。

还原 --skip-worktree 操作

你没有问,但下一个合乎逻辑的问题是,当你对 basic_abc/basic 中的文件进行更改后,将是如何提交它们。我在这里提到它是因为一旦你 运行 那个 --skip-worktree 循环,重命名 basicbasic_abc 和 运行ning git statusgit add 不行!

幸运的是,这个问题已经在 SO 上得到了一半的回答: 展示了如何列出跳过的文件,这个命令可以将它们恢复为未被跳过的状态:

git ls-files -v . |
   grep "S src/main/resources/basic_abc" |
   sed "s/^S //" |
   xargs git update-index --no-skip-worktree

我不确定 git ls-files -v . 输出是否像 git status --porcelain 输出一样稳定,特别是因为 -t/-v/-f 选项在手册中标记为 semi-deprecated ,但这目前有效,我不知道如何从 Git.

中提取该列表

注意事项,或者您不应该这样做的原因

感谢@bk2204 链接到 Git FAQ: How do I ignore changes to a tracked file?,它基本上说“不要”。

update-index 有问题,因为它只更新索引,而不是其他一些持久标志。有关这些问题,请参阅 @torek's excellent write up

我想在这里强调的关键点是,一旦您签出沙箱中的另一个分支,您将丢失之前设置的 skip-worktree 位。

刚刚测试:

# do the --skip-worktree operation above
git checkout some-feature-branch
git checkout master

现在我的沙盒有 basic/*basic_abc/*,即所有这些文件的两个完整副本。

所以我的最后一点是,只有在您不打算更改该沙箱中的分支时才使用此解决方案。 (因为我一直在改变分支,对我来说,这等同于“不要使用这个解决方案”。)

更好的解决方案?

我认为最好的方法是完全重新考虑您的设置。您不应修改沙箱,而应编写一些 install/deploy 脚本来创建沙箱外部所需的 run-time 结构。然后你有一个明确的分离和完全的灵活性:源代码在 Git 管理之下,部署的代码具有它需要的任何结构,在 Git 管理之外。如果您想避免实际复制,您可以使用符号链接使部署的结构轻量级并可动态更新。

您可以使用 git rm <folder> --cached - 需要时您可以使用 git add <folder> 再次添加文件夹。请注意,如果您在 re-adding 文件夹之前执行 git commit -a,删除将出现在该提交中。

重要提示:

--cached 参数很重要 - 否则,git 将从您的硬盘中删除文件夹。