如何从 Git 中的未暂存更改中删除说“旧模式 100755 新模式 100644”的文件?

Posted

技术标签:

【中文标题】如何从 Git 中的未暂存更改中删除说“旧模式 100755 新模式 100644”的文件?【英文标题】:How do I remove files saying "old mode 100755 new mode 100644" from unstaged changes in Git? 【发布时间】:2010-11-18 11:02:07 【问题描述】:

出于某种原因,当我最初从存储库中提取我的一个 git 项目时, 我的工作副本中有大量文件没有对它们进行明显的更改,但仍然出现在我的unstaged changes 区域中。

我在 Windows xp 上使用 Git Gui,当我去查看文件以查看发生了什么变化时。 我看到的是:

old mode 100755  
new mode 100644  

有人知道这是什么意思吗?

如何将这些文件从我的未暂存更改列表中取出? (非常烦人必须浏览 100 个文件,只是为了挑选出我最近编辑并想要提交的文件)。

【问题讨论】:

有关core.filemode 的完整、血腥细节,请参阅my answer here。请注意,每个 Git 存储库都应该有自己的 core.filemode 设置,由 Git 在 Git 创建该存储库时设置;该设置应该是该存储库的正确设置。如果由于某种原因出错,您可以更改它。 【参考方案1】:

在我看来,这类似于 unix 文件权限模式(755=rwxr-xr-x644=rw-r--r--) - 旧模式包含 +x(可执行)标志,新模式不包含。

This msysgit issue's replies 建议将 core.filemode 设置为 false 以解决此问题:

git config core.filemode false

【讨论】:

+1。这意味着 git 认为它可以在签出的文件上正确设置可执行位,但是当它尝试这样做时它不起作用(或者至少不是以它可以读取的方式)。然后当它读回这些文件的状态时,看起来可执行位已被故意取消设置。将 core.filemode 设置为 false 告诉 git 忽略文件系统上的任何可执行位更改,因此它不会将其视为更改。如果您确实需要进行可执行位更改,这确实意味着您必须手动执行git update-index --chmod=(+|-)x <path> 如果像我一样,模式更改很重要,您可以将 core.filemode 设置为 false,提交您的实际代码更改,然后将 core.filemode 设置为 true,git 将保留文件更改。 我遇到了同样的问题,但这是由于通过 SSH git cmd 行和 Windows 中映射驱动器上的 Git 扩展使用了相同的 git repro! . .解决方法是一样的,添加到"config" [core] filemode = false @robsch 您可以使用git config --global ... 在全局配置文件中设置选项。 您可以使用git config -l --show-origin 查看每个设置的来源。【参考方案2】:

你可以试试 git reset --hard HEAD 将 repo 重置为预期的默认状态。

【讨论】:

如果 git 在拉取后无法正确/一致地设置可执行位,那么在重置后它不会变得更好。 我将一些项目移动到 USB 驱动器 (fat32) 并再次返回到我的 ubuntu 机器 (ext4) 并最终得到了一堆更改的文件,以及属性。 git reset --hard HEAD 非常适合我。谢谢 -1。 OP 声明“只是为了挑选出我最近编辑并想要提交的文件”。这也会删除这些编辑。 -1 在 git 中建议这个命令类似于说“你可以 rm -rf ./,我相信它不会有任何意想不到的后果”。 不,这没有帮助,这就是问题所在。您重置并清理,仍然 git status 显示模式更改。这是 windows git 的一个严重问题,我认为应该修复它,而不仅仅是通过忽略文件模式来解决。【参考方案3】:

core.filemode 设置为false 确实有效,但请确保~/.gitconfig 中的设置不会被.git/config 中的设置覆盖。

【讨论】:

去过那里,做到了。可悲的是,我自己解决了问题后才找到您的评论。不过,+1! 如果其他用户在 Windows 上克隆此项目,最好将更改应用到 ~/.gitconfig 文件! 如果你想检查 Windows Powershell。 git config --list --show-origin | sls filemode 或在 Linux 上 git config --list --show-origin | grep filemode。这将显示您需要在哪里进行调整。 core.filemode 设置应该每个 .git/config 中设置。它会在 Git 创建新存储库时自动创建,在 git clonegit init 期间,取决于您的操作系统和文件系统的工作方式。它不应该是错误的,但如果是,那就是修复设置的地方:在一个特定的存储库中。【参考方案4】:

您似乎更改了目录的某些权限。我做了以下步骤来恢复它。

$  git diff > backup-diff.txt                ### in case you have some other code changes 

$  git checkout .

【讨论】:

【参考方案5】:

我只有一个更改权限的麻烦文件。 要单独回滚,我只是使用rm <file> 手动删除它,然后进行结帐以提取新副本。

幸运的是我还没有上演它。

如果我有,我可以在运行 git checkout -- <file> 之前运行 git reset -- <file>

【讨论】:

【参考方案6】:

当您拉取并且所有文件在远程存储库中都可以执行时,就会发生这种情况。再次使它们可执行将使一切恢复正常。

chmod +x <yourfile> //For one file
chmod +x folder/* // For files in a folder

您可能需要这样做:

chmod -x <file> // Removes execute bit

相反,对于未设置为可执行文件并且由于上述操作而更改的文件。有一个更好的方法可以做到这一点,但这只是一个非常快速和肮脏的修复。

【讨论】:

是的,但这会产生一个必须稍后提交的更改,对吧?【参考方案7】:

我在从旧硬盘复制带有工作文件的 git repo 几次时遇到了这个问题。问题源于所有者和权限从旧驱动器/机器更改为新驱动器/机器的事实。总而言之,运行以下命令来解决问题 (thanks to this superuser answer):

sudo chmod -R -x . # remove the executable bit from all files

前一个命令实际上会解决 git diff 报告的差异,但会取消您列出目录的能力,因此ls ./ 失败并显示ls: .: Permission denied。要解决这个问题:

sudo chmod -R +X . # add the executable bit only for directories

坏消息是,如果您确实有任何文件要保持可执行,例如.sh 脚本,则需要恢复这些文件。您可以对每个文件使用以下命令:

chmod +x ./build.sh # where build.sh is the file you want to make executable again

【讨论】:

谢谢,帮了我很多忙!还应该检查git config core.filemode 是否设置为true,否则不会检测到权限更改。我还需要在每次更改后刷新 git 索引以获取它。 如果您担心受影响的依赖关系,此解决方案是最安全的。【参考方案8】:

我在用 master 区分我的分支时遇到了这个问题。当我期望我的分支与 master 相同时,Git 返回了一个“模式”错误。我通过删除文件然后再次合并master来修复。

首先我运行了差异:

git checkout my-branch
git diff master

返回:

diff --git a/bin/script.sh b/bin/script.sh
old mode 100755
new mode 100644

然后我运行以下修复:

rm bin/script.sh
git merge -X theirs master

在此之后,git diff 没有返回 my-branch 和 master 之间的差异。

【讨论】:

什么是theirs theirs 告诉合并使用另一个分支(不是当前分支,称为ours)中的版本。有关ourstheirs here 的更多信息。【参考方案9】:

我也遇到过同样的问题。这救了我的命:

这会将所有权限恢复为差异,因此您将一无所有,只剩下您对文件所做的更改。

https://gist.github.com/jtdp/5443498

git diff -p -R --no-color \
| grep -E "^(diff|(old|new) mode)" --color=never  \
| git apply

【讨论】:

它有什么作用?【参考方案10】:

您可以使用以下命令更改文件模式。 git add --chmod=+x -- filename 然后提交到分支。

【讨论】:

【参考方案11】:

这通常在 Windows 和 Linux/Unix 机器之间克隆 repo 时发生。

只需告诉 git 忽略文件模式更改。以下是几种方法:

    仅为当前仓库配置:

     git config core.filemode false
    

    全局配置:

     git config --global core.filemode false
    

    加入~/.gitconfig:

     [core]
          filemode = false
    

只需选择其中一个。

【讨论】:

全局配置不起作用,因为(我猜)git 创建了一个将此选项设置为 true 的 repo(我在 linux 中创建了一个 repo) 何时需要应用这些更改?【参考方案12】:

设置git config core.filemode false 的公认答案有效,但有后果。将core.filemode 设置为 false 告诉 git 忽略文件系统上的任何可执行位更改,因此它不会将其视为更改。如果您确实需要在以后的任何时间对此存储库进行可执行位更改,则必须手动执行,或将 core.filemode 设置回 true。

如果所有修改后的文件都应该具有模式 100755,那么一个不太重要的替代方法是执行类似的操作

chmod 100755 $(git ls-files --modified)

它只是完全改变模式,不多也不少,没有额外的影响。

(在我的情况下,这是由于 OneDrive 与我在 MacOS 上的文件系统同步;通过不更改 core.filemode,我保留了未来可能再次发生模式更改的可能性;在我的情况下,我想知道它是否会再次发生,并且更改 core.filemode 会将它隐藏起来,我不想要)

【讨论】:

【参考方案13】:

这对我有用:

git ls-files -m | xargs -L 1 chmod 644

【讨论】:

【参考方案14】:

此解决方案会将 git 文件权限从 100755 更改为 100644,并将更改推送回 bitbucket 远程仓库。

    查看您的 repo 的文件权限:git ls-files --stage

    如果 100755 而你想要 100644

然后运行以下命令: git ls-files --stage | sed 's/\t/ /g' |剪切-d''-f4 | xargs git update-index --chmod=-x

    现在再次检查你的 repo 的文件权限:git ls-files --stage

    现在提交您的更改:

git 状态

git commit -m "恢复正确的文件权限"

git 推送

【讨论】:

【参考方案15】:

这类似于 bkm 发现的内容,但它也考虑了所有已删除的文件,并且仅在应用更改时发出警告。

这可以很好地从以前的提交中恢复文件模式设置。

git diff -p --no-ext-diff --no-color --diff-filter=d | grep -E "^(diff|old mode|new mode)" | sed -e "s/^old/NEW/;s/^new/old/;s/^NEW/new/" | git apply

【讨论】:

以上是关于如何从 Git 中的未暂存更改中删除说“旧模式 100755 新模式 100644”的文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何撤消 git 中的最后一次提交,但保持我的更改未暂存?

Git stash uncached:如何存放所有未暂存的更改?

放弃Git中未暂存的更改

Git 提交添加/删除未暂存提交的文件

git 撤销更改

提交后将 git 存储库和工作目录复制到另一个位置,在检查状态时给出“未暂存的更改”