
[英]How to stop tracking file in Git BUT allow “ignorable” changes to it on local copy?
[英]How to stop tracking and ignore changes to a file in Git?
我克隆了一个包含一些.csproj
文件的项目。 我不需要/不喜欢我的本地csproj
文件被 Git 跟踪(或在创建补丁时被提出),但显然项目中需要它们。
我已将*.csproj
添加到我的 LOCAL .gitignore
中,但这些文件已经在 repo 中。
当我输入 git 状态时,它显示我对csproj
的更改,我对跟踪或提交补丁不感兴趣。
如何从我的个人存储库中删除这些文件的“跟踪”(但将它们保留在源中以便我可以使用它们),以便在我执行状态(或创建补丁)时看不到更改?
是否有正确/规范的方法来处理这种情况?
只需在要从修订控制中删除的每个文件上调用git rm --cached
就可以了。 只要您的本地忽略模式是正确的,您就不会在 git status 的输出中看到这些文件。
请注意,此解决方案会从存储库中删除文件,因此所有开发人员都需要维护自己的本地(非修订控制)文件副本
为了防止 git 检测到这些文件中的更改,您还应该使用以下命令:
git update-index --assume-unchanged [path]
您可能想要做什么:(来自@Ryan Taylor 的回答)
- 这是告诉 git 你想要你自己的独立版本的文件或文件夹。 例如,您不想覆盖(或删除)生产/暂存配置文件。
git update-index --skip-worktree <path-name>
完整的答案在这个 URL 中:http: //source.kohlerville.com/2009/02/untrack-files-in-git/
这将为您保留本地文件,但会在其他任何人拉取时将其删除。
git rm --cached <file-name>
或git rm -r --cached <folder-name>
这是为了优化,就像一个包含大量文件的文件夹,例如可能永远不会改变的 SDK。 它告诉 Git 每次都停止在本地检查那个巨大的文件夹是否有变化,因为它不会有任何变化。 如果文件/文件夹有上游更改(当您拉取时), assume-unchanged
索引将被重置并覆盖文件。
git update-index --assume-unchanged <path-name>
这是告诉 Git 你想要你自己的独立版本的文件或文件夹。 例如,您不想覆盖(或删除)生产/暂存配置文件。
git update-index --skip-worktree <path-name>
重要的是要知道git update-index
不会随 Git 传播,因此每个用户都必须独立运行它。
如果您执行git update-index --assume-unchanged file.csproj
,git 不会自动检查 file.csproj 的更改:这将阻止它们在您更改它们时以 git 状态出现。 因此,您可以通过这种方式标记所有 .csproj 文件——尽管您必须手动标记上游存储库发送给您的任何新文件。 (如果您在.gitignore
或.git/info/exclude
中有它们,那么您创建的将被忽略)
我不完全确定 .csproj 文件是什么......如果它们与 IDE 配置类似(类似于 Eclipse 的 .eclipse 和 .classpath 文件),那么我建议它们永远不应该在源代码控制全部。 另一方面,如果它们是构建系统的一部分(如 Makefiles),那么显然它们应该——并且一种获取可选本地更改的方法(例如从 local.csproj 和 la config.mk)将很有用:将构建分为全局部分和局部覆盖。
这是一个两步过程:
删除文件/文件夹的跟踪 - 但将它们保留在磁盘上 - 使用
git rm --cached
现在它们没有显示为“已更改”,但仍显示为
untracked files in git status -u
将它们添加到.gitignore
如果您在本地拥有整个项目但忘记添加 git ignore 并且现在正在跟踪一些不必要的文件,请使用此命令删除所有内容
git rm --cached -r .
确保您位于项目的根目录。
然后你可以照常做
git add .
git commit -m 'removed all and added with git ignore'
git push origin master
希望这可以帮助那些不得不对他们的.gitignore
进行更改或完全忘记它的人。
正如其他答案中指出的那样,所选答案是错误的。
另一个问题的答案表明可能需要跳过工作树。
git update-index --skip-worktree <file>
该答案链接到一篇文章 ( http://fallengamer.livejournal.com/93321.html ) 并引用了这篇文章,并对 --assume-unchanged 和 --skip-worktree 之间的区别进行了很好的总结,如下所示:
--assume-unchanged假定开发人员不应该更改文件。 此标志旨在提高 SDK 等不更改文件夹的性能。
--skip-worktree当您指示 git 不要碰特定文件时很有用,因为开发人员应该更改它。 例如,如果上游的主存储库托管了一些生产就绪的配置文件,并且您不想意外提交对这些文件的更改,那么 --skip-worktree 正是您想要的。
所有的功劳归功于他们的研究和回答。 在这里包含此信息纯粹是为了方便他人。
防止通过 git 监控文件或路径
git update-index --assume-unchanged [file-path]
并将其恢复使用
git update-index --no-assume-unchanged [file-path]
为了节省一些时间,您添加到 .gitignore 的规则可用于删除多个文件/文件夹,即
git rm --cached app/**/*.xml
或者
git rm --cached -r app/widgets/yourfolder/
ETC
很多人建议您使用git update-index --assume-unchanged
。 事实上,这可能是一个很好的解决方案,但只是在短期内。
您可能想要做的是: git update-index --skip-worktree
。
(您可能不想要的第三个选项是: git rm --cached
。它将保留您的本地文件,但将被标记为从远程存储库中删除。)
前两个选项之间的区别?
assume-unchanged
是临时允许您隐藏文件中的修改。 如果你想隐藏对文件所做的修改,修改文件,然后签出另一个分支,你必须使用no-assume-unchanged
然后可能隐藏修改完成。skip-worktree
都会跟随您进行修改! assume-unchanged
的用例
它假定不应修改此文件,并在执行git status
时为您提供更清晰的输出。 但是当签出到另一个分支时,您需要重置标志并在此之前提交或存储更改。 如果您在激活此选项的情况下进行拉取,您将需要解决冲突并且 git 不会自动合并。 它实际上只隐藏修改( git status
不会显示标记的文件)。
当我只想停止跟踪更改一段时间+提交与相同修改相关的一堆文件( git commit -a
)时,我喜欢使用它。
skip-worktree
的用例
您有一个设置类,其中包含您的朋友必须根据他们的设置相应地更改的参数(例如,包括密码)。
git update-index --skip-worktree MySetupClass.java
无论分支如何,您所做的修改都将跟随您。 警告:如果你的朋友也想修改这个类,他们必须有相同的设置,否则他们的修改会被推送到远程仓库。 拉动时,文件的远程版本应覆盖您的文件。
PS:做一个或另一个,但不要同时做,因为你会有不良的副作用。 如果你想尝试另一个标志,你应该先禁用后者。
要告诉 Git 不要跟踪对本地文件/文件夹的更改(意味着 git status 不会检测到对它的更改),请执行以下操作:
git update-index --skip-worktree path/to/file
并告诉 Git 再次跟踪对本地版本的更改(以便您可以提交更改),请执行以下操作:
git update-index --no-skip-worktree path/to/file
一行回答git update-index --assume-unchanged [path]
只要您有一个位于中央仓库和本地仓库中的文件,就可以使用它。您需要在该文件中进行更改,但不得暂存/提交到中央仓库。 此文件不应添加到.gitignore
中。 因为如果系统管理员引入文件中的新更改,高级开发人员需要分布在所有本地存储库中。
最佳示例:数据库连接的配置文件。 在中央存储库中,您将拥有所有用户名、密码、主机、端口以及生产数据库服务器的值。 但是在本地开发中,您应该只使用本地或任何其他开发数据库服务器(您的团队已经设置)。 在这种情况下,您想在配置文件中进行更改,但不应该提交到中央仓库。
最好的
此方法应用标准的 .gitignore 行为,不需要手动指定需要忽略的文件。
不能再使用
--exclude-from=.gitignore
了:/ - 这是更新的方法:一般建议:从一个干净的 repo 开始——所有内容都已提交,工作目录或索引中没有任何待处理的内容,并进行备份!
#commit up-to-date .gitignore (if not already existing)
#this command must be run on each branch
git add .gitignore
git commit -m "Create .gitignore"
#apply standard git ignore behavior only to current index, not working directory (--cached)
#if this command returns nothing, ensure /.git/info/exclude AND/OR .gitignore exist
#this command must be run on each branch
git ls-files -z --ignored --exclude-standard | xargs -0 git rm --cached
#optionally add anything to the index that was previously ignored but now shouldn't be:
git add *
#commit again
#optionally use the --amend flag to merge this commit with the previous one instead of creating 2 commits.
git commit -m "re-applied modified .gitignore"
#other devs who pull after this commit is pushed will see the newly-.gitignored files DELETED
如果您还需要从分支的提交历史记录中清除新忽略的文件,或者如果您不希望从未来的 pulls 中删除新忽略的文件,请参阅此答案。
git rm --fileName
git ls-files
以确保文件已被删除或未跟踪
git commit -m "UntrackChanges"
git push
我假设您询问如何删除特定文件夹或 bin 文件夹中的所有文件,而不是单独选择每个文件。
你可以使用这个命令:
git rm -r -f /<floder-name>\*
确保您位于该目录的父目录中。
该命令将递归地“删除” bin/ 或 build/ 文件夹中的所有文件。 删除这个词我的意思是 git 会假装这些文件被“删除”并且这些文件不会被跟踪。 git 确实将这些文件标记为处于删除模式。
请确保您的 .gitignore 已为即将到来的提交做好准备。
文档:git rm
该问题可能是由操作顺序引起的。 如果你先修改了.gitignore,然后git rm --cached xxx,你可能还要继续遇到这个问题。
正确解决方案:
订单不变!
.gitignore 修改后重新加载!
我假设您正在尝试从 git tacking 中删除单个文件。 为此,我建议使用以下命令。
git update-index --assume-unchanged
前 - git update-index --assume-unchanged .gitignore .idea/compiler.xml
要忽略对目录中所有文件(某种类型)的任何更改,我必须结合其中一些方法,否则如果文件以前不存在,则会创建这些文件。
在下面,“excludedir”是我不希望看到更改的目录的名称。
首先,从更改跟踪缓存中删除任何现有的新文件(不从文件系统中删除)。
git status | grep "new file:" | cut --complement -d " " -f1-4 | grep "^excludedir" | xargs git rm --cache
您可以对modified:
执行相同的操作。 renamed:
有点复杂,因为您必须查看新文件名的 post ->
位,并按照下面的deleted:
描述执行 pre ->
位。
deleted:
文件证明有点复杂,因为您似乎无法为本地系统上不存在的文件更新索引
echo .deletedfiles >> .gitignore
git status | grep "deleted:" | cut --complement -d " " -f1-4 | grep "^excludedir" > .deletedfiles
cat .deletedfiles | xargs -d '\n' touch
cat .deletedfiles | xargs -d '\n' git add -f
cat .deletedfiles | xargs -d '\n' git update-index --assume-unchanged
cat .deletedfiles | xargs -d '\n' rm
上面列表中的最后一个命令将再次从文件系统中删除文件,因此请随意省略它。
然后,阻止该目录的更改跟踪
git ls-files excludedir/ | xargs git update-index --skip-worktree
git update index --skip-worktree excludedir/
在这个答案中给出了一种几乎不需要 git 命令的方法:
要忽略每个本地 repo的某些文件:
~/.gitignore_global
,例如通过在终端中touch ~/.gitignore_global
。git config --global core.excludesfile ~/.gitignore_global
一次。~/.gitignore_global
。 例如modules/*.H
,它将被假定在您的工作目录中,即$WORK_DIR/modules/*.H
。要忽略单个本地 repo 的某些文件:
.git/info/exclude
执行上述第三步,即将要忽略的文件/目录路径.git/info/exclude
。 例如modules/*.C
,它将被假定在您的工作目录中,即$WORK_DIR/modules/*.C
。找了半天,想办法做到这一点。 在.gitconfig
中别名一个 git 命令。就像在 android studio 项目中一样,在 checkout 分支之前还原配置文件然后跳过它,在 checkout 分支之后使用sed
将配置文件更改为我的本地配置。 checkoutandmodifylocalproperties = !git update-index --no-skip-worktree local.properties && git checkout local.properties && git checkout $1 && git update-index --skip-worktree local.properties && sed -i '' 's/.*sdk.dir.*/sdk.dir=\\/Users\\/run\\/Library\\/Android\\/sdk/g' local.properties && :
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.