如何停止跟踪并忽略对Git中文件的更改?


1730

我已经克隆了一个包含一些.csproj文件的项目。我不需要/不喜欢我的本地csproj文件被Git跟踪(或在创建补丁时显示),但是显然在项目中需要它们。

我已经将*.csprojLOCAL 添加到了我.gitignore,但是文件已经在仓库中了。

当我输入git status时,它会显示我csproj对跟踪或提交补丁不感兴趣的更改。

如何从个人存储库中删除对这些文件的“跟踪”(但将其保留在源中,以便我可以使用它们),以便在执行状态(或创建补丁程序)时看不到更改?

有没有正确/规范的方法来处理这种情况?


18
这是一个非常有用的问题,但是我很好奇您为什么不想跟踪对.csproj文件的更改,这在任何项目中都非常重要。对.csproj.user文件或任何.Publish.XML我完全理解不跟踪的文件的更改,但是令您感兴趣的是,为什么您不想跟踪.csproj……
Owen Blacker,2012年

7
也许他们使用其他IDE?
耶勒(Jarrett)2013年

3
具有讽刺意味的是,我之所以来到此线程,是因为我希望从存储库中删除.suo文件,但将其保留在本地。为了后代,.Net开发要求您将.csproj文件保留在存储库中,并且除非您想让项目中其他开发人员感到愤怒,否则应始终跟踪这些更改。如果拿不准,先看看gitignore文件回购在GitHub上:github.com/github/gitignore/blob/master/VisualStudio.gitignore
隆达

1
@Cupcake,您链接到的问题是在这之后15天写的?也许您还有其他想法?
stephenmurdoch

@marflar规范问题不一定是最老的问题,只是最好的问题。我联系到一个有20个答案,而这其中只有5

Answers:


2127

只需调用git rm --cached要从版本控制中删除的每个文件,就可以了。只要您的本地忽略模式正确,您就不会在git status的输出中看到这些文件。

请注意,此解决方案从存储库中删除文件,因此所有开发人员都需要维护自己的本地文件副本(不受版本控制)

为了防止git检测到这些文件中的更改,您还应该使用以下命令:

git update-index --assume-unchanged [path]

您可能想做的是:(@Ryan Taylor答案下面)

  1. 这是告诉git您想要自己的文件或文件夹的独立版本。例如,您不想覆盖(或删除)生产/登台配置文件。

git update-index --skip-worktree <path-name>

完整的答案在以下URL中:http : //source.kohlerville.com/2009/02/untrack-files-in-git/


186
“ git rm --cached <文件>”将从版本控制中删除<文件>,同时将其保留在工作库中。无论您想要的是什么
JakubNarębski09年

51
但是当其他人拉存储库时,是否会删除自己的* .csproj文件?因为如果我们要取消跟踪文件,但不删除它。
FMaz008 2011年

23
如果要删除目录中的所有文件,请将其与git ls-files结合使用:git ls-files | xargs git rm --cached-这将删除给定目录中git索引中的所有内容,而不会删除实际文件。
Marco

129
git rm --cached -r <dir>在文件夹及其中的所有文件上递归工作。
克里斯·K

41
这将停止跟踪文件,将其保存在本地,但会导致任何拉出文件的人都将其删除
Edward Newell

249

如果这样做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)的方法将很有用。 :将构建分为全局部分和局部替代。


8
csproj是一个C#项目文件,可跟踪项目中包含哪些文件以及其他一些配置,必须对其进行源代码控制才能使项目正常工作
SparK 2013年

4
这是这里唯一正确的答案!我多年来一直在使用@araqnids答案,它完全可以按照要求解决此问题。
NHDaly 2014年

命令参数中“文件”前缀的含义是什么?为什么不呢.csproj
GreenAsJade 2014年

1
有什么方法可以检测到已针对文件执行此操作,或者检测到回购中已针对哪些文件执行了此操作?我为忘记执行此操作感到有些紧张,然后想知道为什么以后该文件没有得到更新!
GreenAsJade 2014年

4
@GreenAsJade:git ls-files -v将使用小写字母显示假定未更改的文件(例如hH对于缓存的文件,通常不会显示)。
阿玛丹2014年

237

有3个选项,您可能想要#3

1.这将为您保留本地文件,但在其他人拉出时将其删除。

git rm --cached <file-name> 要么 git rm -r --cached <folder-name>

2.这是为了进行优化,例如包含大量文件的文件夹,例如,可能永远不会更改的SDK。它告诉git每次都停止在本地检查该大文件夹的更改,因为它没有任何更改。assume-unchanged如果文件/文件夹有上游更改(当您拉时),则索引将被重置并覆盖文件。

git update-index --assume-unchanged <path-name>

3.这是告诉git您想要自己的文件或文件夹的独立版本。例如,您不想覆盖(或删除)生产/登台配置文件。

git update-index --skip-worktree <path-name>

重要的是要知道它git update-index 不会随git一起传播,并且每个用户都必须独立运行它。


8
这个答案是最完整的-它提供了各种解决方案,每个解决方案都有其分支。我正在使用的特定情况在配置文件中嵌入了一个密码。我想传播一个模板文件,然后将密码添加到我的副本中。带有密码的副本应该被忽略并且不能被覆盖。
bmacnaughton

1
我该如何在本地检查哪些文件申请“假定不变”或“跳过工作树”?
Supawat Pusavanno

3
@SupawatPusavanno,以查看您先前选择用于假定不变或跳过工作树的文件,请查看此答案stackoverflow.com/questions/42363881/…-它使用grepgit ls-files
Ryan Taylor

1
很好的答案。但是当我尝试切换到另一个分支时,git抛出错误:错误:“您对以下文件的本地更改将被checkout .....覆盖。”解决方案是在切换之前将更改保存起来,并在取消保存时取消保存你回到分支。
PhantomReference

@RyanTaylor:我尝试先假设不变(不起作用)并跳过工作树命令(不起作用),当我检查git状态时,文件未显示表示该命令有效。但是,当我又从这it gives me error that your local changes would be overwritten两个文件的git origin repo 中再次拉出代码时,这意味着它不是无法跟踪的吗?
NeverGiveUp161

152

这是一个两步过程:

  1. 删除文件/文件夹的跟踪-但将其保留在磁盘上-使用

    git rm --cached 
    

    现在它们不会显示为“已更改”,但仍显示为

        untracked files in  git status -u  
    
  2. 将它们添加到 .gitignore


56
不会,这会将文件从跟踪中删除,将其保存在本地,但会导致任何将其拉出的人都将其删除
爱德华·纽厄尔2014年

1
就我而言,我不小心添加了一个我不想跟踪的文件夹,所以这就是我所需要的。
桑尼2014年

4
是的,这确实是所提出问题的错误答案-但这对于大多数在搜索结果中找到此问题的人(例如我)来说可能是正确的答案。
安德鲁·斯宾塞

95

接受的答案仍然对我不起作用

我用了

git rm -r --cached。

git添加

git commit -m“修复.gitignore”

这里找到答案


该链接非常有用,尤其是以递归方式删除.gitignore中的所有文件时
rmcsharry 2016年

9
我已经在这里返回了3次,希望我可以在下一次之前进行记忆!
哈里·波什

@Edward Newell的上述回答中的注释也适用于此:“这将从跟踪中删除文件,将其保存在本地,但对于任何拉出文件的人,都会将其删除 ”。
ToJo

46

忘记了.gitignore?

如果您在本地拥有整个项目,但忘了添加gitignore,现在正在跟踪一些不必要的文件,请使用此命令删除所有内容

git rm --cached -r .

确保您是项目的根源。

那你可以照常做

git add .

承诺

git commit -m 'removed all and added with git ignore'

git push origin master

结论

希望这可以帮助那些必须对其进行更改.gitignore或一起忘记更改的人们。

  • 它删除了整个缓存
  • 看你的.gitignore
  • 添加您要跟踪的文件
  • 推送到您的仓库

4
当您谈论删除或添加时,您忘记了何时何地。从曲目列表中删除?从存储库?来自本地项目空间?拔下拔?在提交?在推?las,这里的所有作者都有相同的问题。
Gangnus '16

3
@Gangnus我认为没有人“澄清”您要提出的观点,因为完全可以看出文件实际上并未从磁盘或存储库中删除。该答案指定了命令的时间顺序。正如您的评论所暗示的那样,这并不神秘或无法解释。
安东尼

@Edward Newell的上述回答中的注释也适用于此:“这将从跟踪中删除文件,将其保存在本地,但对于任何拉出文件的人,都会将其删除 ”。
ToJo

26

正如其他答案中指出的那样,所选答案是错误的。

另一个问题的答案表明,可能需要跳过工作树。

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

2
不,不是真的:--skip-worktree用于将文件保留在存储库中,但停止跟踪其更改。正如您的回答所说:--skip-worktree在您指示git永远不要触摸特定文件时很有用,因为开发人员应该对其进行更改
Erdal G.

4
@ErdalG。究竟。根据问题,他们希望忽略文件中的任何更改,但将文件保留在存储库中
the_new_mr

与@the_new_mr同意,--assume-unchanged--skip-worktree有类似的效果,但它们的目的是完全不同的。前一个用于通过欺骗git 不检查特定文件来提高git性能,而后一个用于忽略将来对特定文件的更改,这些更改适用于运行时但必不可少的文件。
Victor Wong

22

为了节省时间,您可以将添加到.gitignore的规则用于删除多个文件/文件夹,即

git rm --cached app/**/*.xml

要么

git rm --cached -r app/widgets/yourfolder/

等等


这是一个非常好的解决方案,因为您有可能要逐步修复gitignore
Cutiko


9

很多人建议您使用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

您有一个设置类,其中包含您的朋友必须根据其设置更改的参数(例如,包括密码)。

  • 1:创建此类的第一个版本,填写您可以填写的字段,并将其他字段保留为空/空。
  • 2:提交并将其推送到远程服务器。
  • 3: git update-index --skip-worktree MySetupClass.java
  • 4:使用您自己的参数更新您的配置类。
  • 5:回去工作另一个功能。

您所做的修改将跟随您的任何分支。警告:如果您的朋友也想修改此类,则他们必须具有相同的设置,否则他们的修改将被推送到远程存储库。拉动时,文件的远程版本应覆盖您的文件。

PS:请选择其中一项,但请不要同时使用,因为这会产生不良的副作用。如果要尝试其他标志,则应先禁用后者。


7

要告诉Git不要跟踪对本地文件/文件夹的更改(意味着git status不会检测到对它的更改),请执行以下操作:

git update-index --skip-worktree path/to/file

并告诉Git再次跟踪对本地版本的更改(以便您可以提交更改),请执行以下操作:

git update-index --no-skip-worktree path/to/file

1

一线答案 git update-index --assume-unchanged [path]

每当您有一个文件位于中央存储库和本地存储库中时,都应使用此文件。您需要在该文件中进行更改,但不得暂存/提交给中央存储库。此文件不应添加到中.gitignore。因为文件的新更改(如果由系统管理员引入),则高级开发人员需要在所有本地存储库中分发。

最佳示例:DB连接的配置文件。在中央存储库中,您将拥有所有用户名,密码,主机,端口以及生产数据库服务器的值。但是在本地开发人员中,您应该仅使用本地或任何其他开发数据库服务器(您的团队已设置)。在这种情况下,您想在配置文件中进行更改,但不应提交给中央存储库。

最好


0

我假设你是问如何删除所有文件在一个特定的文件夹或bin文件夹,而不是分别选择每个文件。

您可以使用以下命令:

git rm -r -f /<floder-name>\*

确保您在该目录的父目录中。
该命令将递归“删除” bin /或build /文件夹中的所有文件。用删除一词表示git将假装那些文件被“删除”并且不会跟踪那些文件。git确实将这些文件标记为处于删除模式。

确保确保您的.gitignore准备好即将进行的提交。
文档:git rm


0

该问题可能是由操作顺序引起的。如果先修改.gitignore,然后修改git rm --cached xxx,则可能必须继续遇到此问题。

正确的解决方案:

  1. git rm-缓存的xxx
  2. 修改了.gitignore

顺序不变!

修改后的.gitignore重新加载!


0

我假设您正在尝试从git tacking中删除单个文件。为此,我建议下面的命令。

git update-index-假定不变

以前的git update-index-假定不变的.gitignore .idea / compiler.xml


0

要忽略目录中所有文件(某种类型)的任何更改,我必须结合使用其中一些方法,否则,如果以前不存在这些文件,则会创建这些文件。

在下面,“ excludedir”是我不希望监视更改的目录的名称。

首先,从更改跟踪缓存中删除所有现有的新文件(而不从文件系统中删除)。

git status | grep "new file:" | cut  --complement -d " " -f1-4 | grep "^excludedir" | xargs git rm --cache

您可以使用进行相同的操作modified:renamed:有点复杂,因为您必须查看->新文件名的post 位,并按以下说明进行pre ->deleted:

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/

0

这个答案给出了几乎git无命令的方法

要忽略每个本地仓库的某些文件:

  1. 创建一个文件~/.gitignore_global,例如touch ~/.gitignore_global在终端中。
  2. 运行git config --global core.excludesfile ~/.gitignore_global一次。
  3. 将要忽略的文件/目录路径写入~/.gitignore_global。例如modules/*.H,它将被假定在您的工作目录中,即$WORK_DIR/modules/*.H

要忽略单个本地存储库的某些文件:

  1. .git/info/exclude对仓库中的文件执行上述第三步,即将要忽略的文件/目录路径写入.git/info/exclude。例如modules/*.C,它将被假定在您的工作目录中,即$WORK_DIR/modules/*.C

0

将.gitignore应用于现在/未来

此方法应用标准的.gitignore行为,不需要手动指定需要忽略的文件

不能再使用--exclude-from=.gitignore了:/-这是更新的方法:

一般建议:从干净的仓库开始 -提交的所有东西,在工作目录或索引中没有待处理的东西,然后进行备份

#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

如果您还需要从分支的提交历史记录中清除新忽略的文件,或者您不希望从以后的请求中删除新忽略的文件,请参见此答案


-1

经过长时间的搜索,找到了解决方法。.gitconfig在android studio项目中的.like中别名一个git命令,在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 && :

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.