如何在本地配置Git忽略某些文件?

1817

我可以在本地忽略文件而不会污染全局git配置以便其他人使用吗?我有一些未被追踪的文件在我的git状态中,但我不想为我本地分支中的每个小随机未被追踪的文件提交git配置更改。

16个回答

2485

来自相关的Git文档

特定于某个仓库但不需要与其他相关仓库共享的模式(例如,存储在仓库内但特定于一个用户工作流程的辅助文件)应放入$GIT_DIR/info/exclude文件中。

.git/info/exclude文件具有与任何.gitignore文件相同的格式。另一种选择是将core.excludesFile设置为包含全局模式的文件名。

请注意,如果您已经有未暂存的更改,则必须在编辑忽略模式后运行以下命令:

git update-index --assume-unchanged <file-list>

关于$GIT_DIR的说明:这是Git手册中广泛使用的一种表示Git仓库路径的符号。如果设置了环境变量,则会覆盖当前所在的仓库位置,这可能不是您想要的。


编辑:另一种方法是使用:

git update-index --skip-worktree <file-list>

通过以下方式将其反转:

git update-index --no-skip-worktree <file-list>

240
注意,在将文件添加到排除列表后,请确保运行 git update-index --assume-unchanged [<file>...]。在那之前,这些更改不会被记录。 - tollmanz
36
在使用Git 1.7.9.5版本时,我不需要运行“git update-index…”来使更改生效。 - Jeffrey Martinez
46
只有在你已经对文件做出更改并希望它被忽略时,才需要使用git update-index。如果在进行更改之前更改了排除规则,则不需要这样做。 - Brady Emerson
21
虽然这样做可以使得文件在提交时不会被视为已更改(就像 .gitignore 一样),但与被忽略的文件不同的是,如果您运行 git reset --hard 命令,这些文件仍将被重置为存储库版本。 - Brady Emerson
23
根据https://dev59.com/7mAg5IYBdhLWcg3w1uDy和https://dev59.com/nWYr5IYBdhLWcg3wfaSc#13631525的回答,``skip-worktree`` 更可能比 assume-unchanged 更受青睐。 - danShumway
显示剩余22条评论

483

更新:考虑使用git update-index --skip-worktree [<file>...]代替,感谢@danShumway!请参见Borealid关于两个选项差异的解释


旧回答:

如果您需要忽略已跟踪文件的本地更改(例如对配置文件的本地修改),请使用git update-index --assume-unchanged [<file>...]


8
请注意,我已经将一个文件添加到$GIT_DIR/info/exclude(例如:my-file.php),然后必须运行git update-index --assume-unchanged my-file.php才能开始忽略它。感谢这个技巧! - tollmanz
85
撤销此操作:git update-index --no-assume-unchanged my-file.php - Ray
20
仅供澄清:假定不变(assume-unchanged)适用于已被跟踪的文件(存在于代码库中)... OP 正在询问未被跟踪的文件,在这种情况下,您需要使用 .git/info/exclude (以避免污染经常共享和被跟踪的 .gitignore 文件)。 - dyodji
7
根据https://dev59.com/7mAg5IYBdhLWcg3w1uDy,这被认为是不安全的,如果你不小心的话,你的文件仍然可能会被提交。 这是作为性能辅助工具而设计的,而不是解决此问题的万无一失的解决方案。 - danShumway
3
在阅读你的更新之前,我迫不及待地使用了--assume-unchanged。我用--no-assume-unchanged撤销了它,然后再使用--skip-worktree... 我现在没问题了吗? - Nicolas Miari
显示剩余5条评论

202

将以下行添加到您的 .gitconfig 文件的 [alias] 部分

ignore = update-index --assume-unchanged
unignore = update-index --no-assume-unchanged
ignored = !git ls-files -v | grep "^[[:lower:]]"

现在你可以使用 git ignore my_file 来忽略本地文件的更改,使用 git unignore my_file 来停止忽略这些更改。 git ignored 列出被忽略的文件。

这个答案摘自 http://gitready.com/intermediate/2009/02/18/temporarily-ignoring-files.html


1
!git ls-files -v | grep "^[[:lower:]]" - 你知道如何在Windows命令提示符上执行此操作吗? - Haohmaru
12
安装一个真正的shell(例如Babun提供bash或zsh);) 我了解你的感受,但我最近从Windows切换到Linux,我再也不想使用cmd了。 - xeruf
@Haohmaru,你可以使用WSL(Windows子系统Linux)。 - A Sz
哇!太棒了的命令。 - jo_

145

您有几个选项:

  • 将脏的(或未提交的).gitignore 文件留在您的工作目录中(或使用 topgit 或其他类似的补丁工具自动应用它)。
  • 如果这仅适用于一个树,则将排除内容放入您的 $GIT_DIR/info/exclude 文件中。
  • 运行 git config --global core.excludesfile ~/.gitignore 并将模式添加到您的 ~/.gitignore。 如果您想在所有树之间忽略某些模式,则可以选择此选项。 例如,我使用此选项来忽略.pyc.pyo文件。

此外,请确保在适用时使用模式而不是明确列出文件。


10
我认为您需要使用 git config --global 命令来全局设置选项。 - Josh Lee
11
其实只需要将 .gitignore 添加到 .gitignore 文件中即可 ;)! - Dominik George

105

10
这个stackoverflow问题中,有关于--skip-worktree--assume-unchanged的讨论。 - Merwer
2
我该如何撤销此操作,或查看当前通过 --skipworktree 忽略的文件/模式列表,以便稍后改变主意并重新开始跟踪文件? - Anomaly
1
如何撤销这个操作? - user1735921
5
请使用 git update-index --no-skip-worktree <file> 命令来撤销操作。 - user1735921
3
@Anomaly 要列出被 --skip-worktree 忽略的文件,您需要使用 git ls-files -v | grep ^S 命令。 - Ahmed Kareem
要排除整个文件夹,请尝试使用 git update-index --assume-unchanged $(git ls-files | tr '\n' ' ') 命令,参见此答案 - gustavozapata

68

您可以在您的主目录中添加一个.gitignore文件,即$ HOME/.gitignore~/.gitignore。然后使用以下命令告诉git使用该文件:

git config --global core.excludesfile ~/.gitignore

这是一个正常的 .gitignore 文件,当 Git 决定要忽略什么时,会引用它。由于它位于您的主目录中,因此仅适用于您,不会污染任何项目的 .gitignore 文件。

我已经使用这种方法多年并取得了很好的效果。


谢谢,@EricChen。更新了答案,请尝试使用git check-ignore <文件名>进行验证。如果可行,请告知我。 - JESii
只有去掉等号才能让我成功执行:git config --global core.excludesfile ~/.gitignore - E. Sundin
我在主目录下放置了一个.gitignore文件,并告诉git使用该文件,然后删除了我想要取消跟踪的本地文件。但是,在我推送更改之后,远程存储库也删除了这些文件。我做错了什么吗? - zyy
哇,@xyz; .gitignore 是用于忽略存在于本地目录中的文件。你应该做的是使用 git rm --cached 命令将它们从仓库中删除但保留在本地。你可以通过类似 git reset --soft HEAD^ 的命令回到之前的提交并恢复你的文件。这就是 Git 的美妙之处:所有的历史记录都还在那里。 - JESii

61
你可以安装一些git别名来使这个过程更简单。这会编辑你的.gitconfig文件中的[alias]节点。
git config --global alias.ignore 'update-index --skip-worktree'
git config --global alias.unignore 'update-index --no-skip-worktree'
git config --global alias.ignored '!git ls-files -v | grep "^S"'

这个安装程序为你提供的快捷方式如下:
  • git ignore config.xml
    • Git会假装没有发现任何config.xml的变化,防止你意外提交这些变化。
  • git unignore config.xml
    • Git将重新开始承认你对config.xml所做的更改,允许你再次提交这些更改。
  • git ignored
    • Git将列出所有你以上述方式“忽略”的文件。

我参考了phatmann的答案来构建这些内容,他提出了一个使用--assume-unchanged的版本。

我所呈现的版本使用--skip-worktree来忽略本地更改。有关区别的完整解释,请参见Borealid的答案,但基本上--skip-worktree的目的是让开发人员在不提交更改的情况下更改文件

这里呈现的git ignored命令使用git ls-files -v,并过滤列表,只显示以S标记开头的条目。 S标记表示状态为“跳过工作树”的文件。有关git ls-files显示的完整文件状态列表:请参阅git ls-files-t选项的文档。


3
这对未跟踪的文件不起作用 :< (在OSX上使用git 2.13.5) - Terra Ashley
“!'git ls-files -v | grep "^S"'”中的“!”是否应该存在?我在加上它后无法运行该命令,但是移除后似乎可以正常工作。 - Tiris
在Git别名中加上感叹号(!)会告诉Git去运行一个外部命令,而不是一个Git子命令。我之所以添加它是因为我需要一个shell pipeline,所以我需要从外部调用Git。我刚刚试着删除了感叹号(按照您的建议),但对我来说这并不起作用。我得到了“扩展别名'ignored'失败;'git'不是git命令”的错误。这很合理;没有感叹号:Git将您的命令别名为“git git ls-files…”。 - Birchlabs
谢谢你的解释。我不熟悉git别名,只是在shell中测试了一下,然后再创建别名。 - Tiris
这是一个非常棒的解决方案。由于git按目录跟踪,当您运行上面的别名“git ignore <filename>”时,它仅适用于该目录。当您最终想要对该文件进行更改并提交和推送到远程时,只需使用方便的“git unignore <filename>”暂时重新开始跟踪它即可!谢谢! - nickang
很好,但正如@Tiris所指出的,这并不适用于所有人,对于我在cmder cmd提示符下的Windows也是一样。尝试去掉感叹号,仍然无法工作,并显示相同的消息:usage: git config [<options>] - obeliksz

49

这是一个简短的一行代码,用于排除本地文件。

 echo YOUR_FILE_OR_DIRECTORY >> .git/info/exclude

根据@Vanduc1102的评论。如果没有应用,请在此之后运行以下命令。

git update-index --assume-unchanged YOUR_FILE_OR_DIRECTORY

适用于特定符号链接。 - bvj
2
如果echo命令无法工作,您也可以直接进入.git/info/exclude下的文件夹。 - Umair Hamid
是的,一样的 @UmairHamid - Yuseferi
4
我需要在命令后运行 git update-index --assume-unchanged YOUR_FILE_OR_DIRECTORY - vanduc1102

16

--assume-unchanged和--skip-worktree都不是忽略本地文件的正确方式... 请查看此答案以及git update-index的文档中的注释。对于任何原因经常更改(和/或从一个克隆到另一个更改)且其更改不应提交的文件,则这些文件不应该首先被跟踪。

但是,有两种适当的方法可以在本地忽略文件(两者都适用于未跟踪的文件)。一种是将文件名放入.git/info/exclude文件中,它是.gitignore的本地替代版本,但特定于当前克隆。或使用全局.gitignore(应仅适用于常见的辅助文件,如pyz、pycache等),该文件将在您机器上的任何git repo中被忽略。

要将上述内容自动化(添加到exclude或全局.gitignore中),您可以使用以下命令(将其添加到bash-profile中):

  • 每个克隆本地排除(请注意,由于使用相对路径,因此在调用命令时应该在存储库的根目录中),将##FILE-NAME##更改为.git/info/exclude
  • 全局.gitignore,首先在此处创建全局.gitignore,然后将##FILE-NAME##更改为~/.gitignore

Linux

alias git-ignore='echo $1 >> ##FILE-NAME##'
alias git-show-ignored='cat ##FILE-NAME##'
git-unignore(){
  GITFILETOUNIGNORE=${1//\//\\\/}
  sed -i "/$GITFILETOUNIGNORE/d" ##FILE-NAME##
  unset GITFILETOUNIGNORE
}

MacOS(如果您想要使用sed进行原地修改(即您被强制添加文件扩展名以进行原地替换),则需要.bak文件,因此为了删除.bak文件,我添加了rm filename.bak命令)

alias git-ignore='echo $1 >> ##FILE-NAME##'
alias git-show-ignored='cat ##FILE-NAME##'
git-unignore(){
  GITFILETOUNIGNORE=${1//\//\\\/}
  sed -i.bak "/$GITFILETOUNIGNORE/d" ##FILE-NAME##
  rm ##FILE-NAME##.bak
  unset GITFILETOUNIGNORE
}

然后你可以执行:

git-ignore example_file.txt
git-unignore example_file.txt


5
为了忽略未跟踪的文件,特别是它们位于(少量)未被跟踪的文件夹中,一个简单的解决方法是为每个未跟踪的文件夹添加一个 .gitignore 文件,并在单行中输入 * 后面跟一个换行符。如果未跟踪的文件在一些文件夹中,这是一个非常简单和直接的解决方案。对于我来说,所有的文件都来自一个未跟踪的文件夹 vendor,上述方法很有效。

2
太好了!顺便说一下:这只能工作是因为git只跟踪(并允许您提交)文件,而不是文件夹。 - jmiserez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接