简体   繁体   English

是否不可能停止在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?

I have a directory I no longer want to track. 我有一个我不想再跟踪的目录。 And I even want to remove some files within that directory, without afecting the git. 我什至要删除该目录中的某些文件,而又不影响git。 Means I would like to remove the files and don't have git status to show those changes to be commited, so as to avoid a git pull from another machine would end up removing the files. 意味着我想删除文件并且没有git status来显示要提交的更改,以避免从另一台计算机上进行git pull最终将删除文件。

I already tried the option: 我已经尝试过该选项:

git rm --cached directory/

but that ended up deleting the files after I did a git pull from another machine. 但是最终在我从另一台机器上进行git pull后删除了文件。

Also tried: 还尝试了:

git update-index --assume-unchanged directory/ 

But after deleting the directory I still get an output at git status stating the directory was deleted. 但是在删除目录后,我仍然在git status上得到输出,表明目录已删除。 I have even added that directory to the .gitignore file. 我什至已将该目录添加到.gitignore文件中。

Is it really impossible to perform such, as stated in the answer under Stop tracking a file in git - without having it deleted either locally or on pull ? 如在停止跟踪git中的文件下的答案中所述-确实要执行该操作-而不是在本地删除或在拉时删除它 ,是否真的不可能?

The short answer is "it's not possible". 简短的答案是“不可能”。

The problem is not restricted to (and in fact has nothing to do with) directories. 问题不限于目录(实际上与目录无关)。 It comes about because the files within that directory really are deleted . 这是因为该目录中的文件 确实被删除了 (It's worth noting here as well that Git does not track directories at all, it just creates them when they are needed to contain files.) (在这里还值得注意的是,Git根本不跟踪目录 ,它只是在需要包含文件时才创建目录。)

Let's pick an actual file name, for completeness. 为了完整起见,让我们选择一个实际的文件名。 Call it conf/config.ini . 将其conf/config.ini You clone some repository, and it has a file named conf/config.ini in it, in commit badc0ff , which is the tip commit of branch master . 您克隆了一些存储库,并在其内部有一个名为conf/config.ini的文件,该文件位于commit badc0ff ,该文件是branch master的提示提交。 Your Git checks out this commit, so your Git dutifully creates, in your work-tree, a directory conf and a file named config.ini in that directory. 您的Git签出了该提交,因此您的Git在工作树中尽职地创建了目录conf和该目录中名为config.ini的文件。

Now you command your Git to go fetch ( git fetch ) more revisions. 现在,您命令Git进行获取( git fetch )的更多修订。 There is one new revision after badc0ff , namely 123face . badc0ff之后有一个新修订,即123face Your origin/master now names commit 123face . 现在,您的origin/master名称将提交123face

Next, you command your Git to integrate the changes from badc0ff to 123face (using git merge origin/master or similar). 接下来,您命令Git集成从badc0ff123face的更改(使用git merge origin/master或类似的东西)。 What are the changes? 有哪些变化? Well, along with anything else, someone removed conf/config.ini . 好吧,有人删除了 conf/config.ini So your Git removes conf/config.ini . 因此,您的Git会删除conf/config.ini

(Note: you may be executing these two Git commands by running git pull . All git pull does in this case is run git fetch and then git merge , so you really are using these two other commands. It's the merge step—going from badc0ff to 123face , obtaining and obeying the changes directed by the upstream—that removes the file; and it removes the file because the file really is removed . That's what it takes to get from one commit to the next.) (注意:您可能通过运行git pull来执行这两个Git命令。在这种情况下,所有git pull都需要先运行git fetch ,然后再进行git merge ,所以您实际上是在使用其他两个命令。这是合并步骤-从badc0ff123face ,获取并遵守上游指示的更改,即删除文件;并删除文件,因为文件实际上已删除 。这就是从一次提交到下一次提交所需要的。)

What to do about this 该怎么办

What's missing here—and has never been considered an important design feature—is a way to tell 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的方法:“尽管您可以执行从提交X到提交Y的过渡,从而删除了路径P ,但实际上请不要从工作中删除路径P -tree-仅将其从索引中删除。”

Since this is missing, you need a workaround ... and it's really quite simple. 由于缺少此功能,因此您需要一种解决方法...而且它确实非常简单。 Just check out the previous commit again and save the file—or, equivalently, extract the file from the previous commit without checking it out: 只需再次签出上一个提交并保存文件,或者等效地,从上一个提交中提取文件而不签出:

$ git show HEAD@{1}:conf/config.ini > conf/config.ini

(the HEAD@{1} syntax here is from gitrevisions and means "the commit HEAD pointed to just before we changed it by obeying the change from the upstream"). (这里的HEAD@{1}语法来自gitrevisions ,它的意思是“提交HEAD在我们通过遵循上游更改而指向更改之前指向”)。

(If there are many such files, as in your case, it's probably more convenient to git checkout the previous commit, ie, tell your Git to "go back in time" one step, then rename the entire directory-full-of-files out of the way and go back forward in time to the present. Then you can rename the directory back.) (如果有很多这样的文件,例如您的情况,则git checkout先前的提交可能更方便,例如,告诉您的Git“及时返回”一步,然后将整个目录重命名为文件并及时返回到现在。然后您可以将目录重命名。)

What if your copy of the file is different? 如果您的文件副本不同,该怎么办?

Suppose your conf/config.ini , at the time you have your Git sitting on commit badc0ff , is not quite the same as what's actually in commit badc0ff . 假设你conf/config.ini ,当时你有的Git坐在提交badc0ff ,是不太一样的东西实际上是badc0ff That is, you've modified your configuration. 也就是说,您已经修改了配置。

If you now run git merge (as git pull does) to merge in the changes from 123face , your Git tells you no: it cannot do this. 如果现在运行git merge (如git pull所做的那样)以合并123face的更改,则Git会告诉您“否”:它不能这样做。 The reason is that your work-tree is not "clean"; 原因是您的工作树不干净。 you have changes to a tracked, committed file that you have not committed yourself. 您对尚未提交的跟踪提交文件进行了更改。 Your Git would have to delete the file, which would lose your changes. 您的Git必须删除该文件,这将丢失您的更改。 So this situation is not supposed to happen in the first place. 因此,这种情况首先不应该发生。 To make the merge go, you should commit your changes. 要进行合并,您应该提交更改。 Let's say that you do and you get commit fedbeef as a result. 假设您这样做,并因此得到了fedbeef提交。

Once you do commit your changes, you will be able to merge. 一旦提交你的修改,你就可以进行合并。 You will get a "merge conflict" on merging their "remove the file" with your "I changed the file", and you can resolve that merge conflict by removing the file. 在将他们的“删除文件”与“我更改文件”合并时,会出现“合并冲突”,并且可以通过删除文件来解决合并冲突。 This gets you the right final state (the file is gone, but if you create it, it will be untracked). 这样可以使您获得正确的最终状态(文件已消失,但是如果创建了文件,它将不会被跟踪)。 Then you simply extract your committed version from your commit: 然后,您只需从提交中提取提交的版本:

git show fedbeef:conf/config.ini > conf/config.ini

and all is good. 一切都很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM