git 可以远程忽略文件,同时在本地包含它吗?

Can git ignore a file remotely, while including it locally?

我正在做一个 ASP.NET 项目,当我在我的桌面上进行本地开发时,我需要有 connectionStrings 来连接到数据库,但不想将它们签入网络上的 tfs 存储库。将 ConnectionStrings.config 文件放在 gitignore 文件中很容易排除。但这也阻止了它被保存在我正在工作的分支的本地副本中,所以每次我在本地分支之间切换时,我的配置文件都会消失。

有没有什么方法可以在本地提交但远程忽略?

如果您切换分支,被忽略的文件会保留在原地。如果您将 ConnectionStrings.config 文件添加到所有分支(或共同祖先)上的 .gitignore,它应该始终存在(直到您执行完整的 git clean)。

一个问题是如果一个新人第一次克隆,这个文件是不存在的。对于这种情况,有些人有一个模板示例配置文件,例如 ConnectionStrings.config.example,其中包含一些您提交(而不是忽略)的虚假示例数据。在你第一次克隆之后做一个 copy ConnectionStrings.config.example ConnectionStrings.config 并修改真实的配置。

另一种解决方案(尽管有点临时)是,如果您有 3 个开发人员在该站点上工作,您可以有一个 ConnectionStrings.config,其中包含他们本地环境的多个连接字符串,名称不同,比如 "BobDevDB"、"AliceDevDB"、"JohnDevDB",每个名称前缀类似于他们的开发计算机名称或他们的 Windows 用户名,以便您可以在运行时选择正确的连接字符串。这样你就不必忽略任何东西,它总是有效的。

Is there some way to commit locally but ignore remotely?

没有

更准确地说,不是你想的那样。当您意识到 Git 在某种程度上根本不关心 文件 时,您 可以 做什么就变得很明显了。 Git 关心的——以及从存储库到存储库的传输——是 提交 。对于使用提交图的 Git 算法来说,其中的重要部分是提交及其 parent / child 关系。文件只是顺其自然。

假设您从存储库中的一些提交开始,这些提交是从其他存储库复制的(这样另一个存储库也有这两个分支):

...--o--o--o   <-- master
         \
          o--o   <-- develop

这里的每一轮o代表一次提交。您创建了一个新分支 work 指向 相同的 提交 develop 指向:

...--o--o--o   <-- master, origin/master
         \
          o--o   <-- develop, origin/develop, work (HEAD)

origin/* 的名字是你 Git 记住你的 Git 在 他们的 Git 上看到的东西的方式,所以只要你的 Git 没有从他们那里得到任何新的东西,你的 origin/* 名称仍然指向这些相同的提交。)

现在您在新分支上做一些工作并提交。让我们将这个新提交称为 A 以便我们讨论它(实际上它有一些丑陋的哈希 ID):

...--o--o--o   <-- master, origin/master
         \
          o--o   <-- develop, origin/develop
              \
               A   <-- work (HEAD)

如果您 git push 从您的 Git 存储库,您可以提供的唯一新 提交 A.

提交A的实际ID,丑陋的大哈希,取决于一切关于提交A:这包括 附加到 提交 A 的所有文件,以及您的 develop 指向的提交是提交 A 的事实parent.

如果您将提交 A 提交给其他人 Git,您有义务将与提交 A 相关的每个 文件 提交给他们.如果他们没有所有文件,他们就没有提交 A.

可以 进行新的提交——让我们称之为 A'——那是很多 like A,只是略有不同。让我们使 A' 没有文件。不过,它的 parent 与 A 的 parent 相同,并且它包含所有 other 文件——记住,每次提交都是完整的A 拥有的所有文件的快照。让我们用 git checkout developA' 放在 develop 上,然后复制 A 除了我们省略一个文件:

...--o--o--o   <-- master, origin/master
         \
          o--o   <-- origin/develop
             |\
             | A'  <-- develop (HEAD)
             \
               A   <-- work

现在你可以让你的 Git 打电话给另一个 Git 并提供,不是 A,而是 A',通过你的名字 develop .如果他们选择接受,您的 Git 现在会记住 他们的 develop 指向 A'.

这种特殊的方法使用起来相当痛苦。如果你能找到其他方法,这不是要走的路。

我们发现了问题。这个项目有几个开发分支,并不是所有的分支都将 ConnectionStrings.config 添加到他们的 .gitignore 中。所以有人在其中一个分支中使用 ConnectionStrings.config 连接到数据库,当他们签入代码时,他们也签入了配置文件。

解决方案分为两部分。首先,我们必须更新所有活动开发分支的 .gitignore,以便它们忽略配置文件。然后我们不得不从该分支的缓存中删除该文件。通过 Visual Studio 的团队资源管理器没有明显的方法可以做到这一点,所以我们结束了在命令行上使用 --cached 选项。

git rm -r --cached .\ProjectName\ConnectionStrings.config

幸运的是,只有几个分支处于这种状态,并且很容易修复它们,将它们与原点同步,并修复每个人的本地分支。