是否无法停止跟踪 git 中的目录并在本地删除它以确保它在 git 从另一台机器上拉出后仍然存在?
Is it impossible to stop tracking a directory in git and remove it locally ensuring it will remaing after a git pull from another machine?
我有一个我不想再跟踪的目录。我什至想删除该目录中的一些文件,而不影响 git。意味着我想删除文件并且没有 git 状态来显示要提交的更改,以避免从另一台机器上拉取 git 最终删除文件。
我已经尝试过以下选项:
git rm --cached directory/
但在我从另一台机器上执行 git 拉取操作后最终删除了文件。
也尝试过:
git update-index --assume-unchanged directory/
但是在删除目录后,我仍然在 git 状态下得到一个输出,表明目录已被删除。我什至将该目录添加到 .gitignore 文件中。
Stop tracking a file in git - without having it deleted either locally or on pull 下的回答中所说的那样真的不可能执行吗?
简短的回答是 "it's not possible"。
问题不限于(实际上与目录无关)。这是因为该目录 中的 文件 确实被删除了 。 (这里也值得注意 Git 根本不跟踪 目录 ,它只是在需要它们包含文件时创建它们。)
为了完整起见,让我们选择一个实际的文件名。称之为conf/config.ini
。您克隆了某个存储库,其中有一个名为 conf/config.ini
的文件,在提交 badc0ff
中,这是分支 master
的提示提交。您的 Git 检查此提交,因此您的 Git 尽职尽责地在您的工作树中创建一个目录 conf
和该目录中名为 config.ini
的文件。
现在您命令 Git 去获取 (git fetch
) 更多修订。 badc0ff
之后有一个新的修订,即123face
。您的 origin/master
现在命名为提交 123face
.
接下来,您命令 Git 整合从 badc0ff
到 123face
的更改(使用 git merge origin/master
或类似方法)。有哪些变化?好吧,连同其他事情,有人 删除了 conf/config.ini
。所以你的 Git 删除了 conf/config.ini
.
(注意:您可能正在通过 运行ning git pull
执行这两个 Git 命令。在这种情况下,git pull
所做的只是 运行 git fetch
然后 git merge
,所以你真的 是 使用这两个其他命令。这是合并步骤 — 从 badc0ff
到 123face
,获取并服从上游指示的更改——删除文件;它删除文件是因为文件 确实被删除了 。这就是从一个提交到下一个提交所需要的.)
怎么办
这里缺少的——并且从未被认为是重要的设计特征——是一种告诉 Git 的方法:"Although you may execute a transition from commit X to commit Y that removes path P, please don't actually remove path P from the work-tree—remove it from the index only."
由于缺少这个,您需要一个解决方法...而且它真的很简单。只需再次检查之前的提交并保存文件——或者,等效地,从之前的提交中提取文件而不检查它:
$ git show HEAD@{1}:conf/config.ini > conf/config.ini
(此处的 HEAD@{1}
语法来自 gitrevisions,意思是 "the commit HEAD
pointed to just before we changed it by obeying the change from the upstream")。
(如果有很多这样的文件,就像你的情况一样,git checkout
上一次提交可能更方便,即告诉你的 Git 到 "go back in time" 一步,然后重命名整个目录 - 充满文件的方式并及时回到现在。然后你可以重命名目录。)
如果您的文件副本不同怎么办?
假设您的 conf/config.ini
,在您 您的 Git 提交 badc0ff
时,与实际上 在 中提交 badc0ff
。也就是说,你已经修改了你的配置。
如果您现在 运行 git merge
(如 git pull
所做的那样)合并来自 123face
的更改, 您的 Git告诉你 no: 它不能这样做。原因是您的工作树不是 "clean";您对跟踪的已提交文件进行了更改,但您自己并未提交。您的 Git 将不得不删除该文件,这将丢失您的更改。所以这种情况本来就不应该发生的。要进行合并,您应该提交更改。假设您这样做了,结果您得到了提交 fedbeef
。
提交更改后,您就可以合并了。您将在将他们的 "remove the file" 与您的 "I changed the file" 合并时得到 "merge conflict",您可以通过删除文件来解决合并冲突。这使您获得正确的最终状态(文件已消失,但如果您创建它,它将被取消跟踪)。然后你只需从你的提交中提取你提交的版本:
git show fedbeef:conf/config.ini > conf/config.ini
一切都很好。
我有一个我不想再跟踪的目录。我什至想删除该目录中的一些文件,而不影响 git。意味着我想删除文件并且没有 git 状态来显示要提交的更改,以避免从另一台机器上拉取 git 最终删除文件。
我已经尝试过以下选项:
git rm --cached directory/
但在我从另一台机器上执行 git 拉取操作后最终删除了文件。
也尝试过:
git update-index --assume-unchanged directory/
但是在删除目录后,我仍然在 git 状态下得到一个输出,表明目录已被删除。我什至将该目录添加到 .gitignore 文件中。
Stop tracking a file in git - without having it deleted either locally or on pull 下的回答中所说的那样真的不可能执行吗?
简短的回答是 "it's not possible"。
问题不限于(实际上与目录无关)。这是因为该目录 中的 文件 确实被删除了 。 (这里也值得注意 Git 根本不跟踪 目录 ,它只是在需要它们包含文件时创建它们。)
为了完整起见,让我们选择一个实际的文件名。称之为conf/config.ini
。您克隆了某个存储库,其中有一个名为 conf/config.ini
的文件,在提交 badc0ff
中,这是分支 master
的提示提交。您的 Git 检查此提交,因此您的 Git 尽职尽责地在您的工作树中创建一个目录 conf
和该目录中名为 config.ini
的文件。
现在您命令 Git 去获取 (git fetch
) 更多修订。 badc0ff
之后有一个新的修订,即123face
。您的 origin/master
现在命名为提交 123face
.
接下来,您命令 Git 整合从 badc0ff
到 123face
的更改(使用 git merge origin/master
或类似方法)。有哪些变化?好吧,连同其他事情,有人 删除了 conf/config.ini
。所以你的 Git 删除了 conf/config.ini
.
(注意:您可能正在通过 运行ning git pull
执行这两个 Git 命令。在这种情况下,git pull
所做的只是 运行 git fetch
然后 git merge
,所以你真的 是 使用这两个其他命令。这是合并步骤 — 从 badc0ff
到 123face
,获取并服从上游指示的更改——删除文件;它删除文件是因为文件 确实被删除了 。这就是从一个提交到下一个提交所需要的.)
怎么办
这里缺少的——并且从未被认为是重要的设计特征——是一种告诉 Git 的方法:"Although you may execute a transition from commit X to commit Y that removes path P, please don't actually remove path P from the work-tree—remove it from the index only."
由于缺少这个,您需要一个解决方法...而且它真的很简单。只需再次检查之前的提交并保存文件——或者,等效地,从之前的提交中提取文件而不检查它:
$ git show HEAD@{1}:conf/config.ini > conf/config.ini
(此处的 HEAD@{1}
语法来自 gitrevisions,意思是 "the commit HEAD
pointed to just before we changed it by obeying the change from the upstream")。
(如果有很多这样的文件,就像你的情况一样,git checkout
上一次提交可能更方便,即告诉你的 Git 到 "go back in time" 一步,然后重命名整个目录 - 充满文件的方式并及时回到现在。然后你可以重命名目录。)
如果您的文件副本不同怎么办?
假设您的 conf/config.ini
,在您 您的 Git 提交 badc0ff
时,与实际上 在 中提交 badc0ff
。也就是说,你已经修改了你的配置。
如果您现在 运行 git merge
(如 git pull
所做的那样)合并来自 123face
的更改, 您的 Git告诉你 no: 它不能这样做。原因是您的工作树不是 "clean";您对跟踪的已提交文件进行了更改,但您自己并未提交。您的 Git 将不得不删除该文件,这将丢失您的更改。所以这种情况本来就不应该发生的。要进行合并,您应该提交更改。假设您这样做了,结果您得到了提交 fedbeef
。
提交更改后,您就可以合并了。您将在将他们的 "remove the file" 与您的 "I changed the file" 合并时得到 "merge conflict",您可以通过删除文件来解决合并冲突。这使您获得正确的最终状态(文件已消失,但如果您创建它,它将被取消跟踪)。然后你只需从你的提交中提取你提交的版本:
git show fedbeef:conf/config.ini > conf/config.ini
一切都很好。