我又迷失了git。我的情况是这样:
我有一个远程存储库,我push
在其中存放了本地存储库。然后我注意到其中有2个docker文件。一个命名为Dockerfile
,另一个命名为Dockerfile (local_model)
。我还注意到,我只需要1个Dockerfile
,就必须是Dockerfile (local_model)
。
换句话说,我需要删除Dockerfile
,然后将Dockerfile (local_model)
重命名为Dockerfile
。
我使用以下命令来实现它:
git rm --cached path/to/Dockerfile
git commit -m "Deleted a file"
git push -u origin master
该文件删除了远程存储库中的文件(我在浏览器中检查了它,似乎已经起作用了。)
然后我用了:
git mv "path/to/Dockerfile (local_model)" "path/to/Dockerfile"
致命:目的地存在, 源=路径/到/ Dockerfile (local_model), destination = path / to / Dockerfile
这阻止了我重命名该文件,因为存在另一个同名文件。我设法使用以下方法重命名了文件:
git mv --force "path/to/Dockerfile (local_model)" "path/to/Dockerfile"
毕竟(以及之后也应用commit ...
和push..
),但我感到困惑。
与目标文件同名的文件在哪里?我知道此命令仅影响远程存储库,因此与本地存储库不应有任何冲突,对吧?
答案 0 :(得分:2)
eftshift0's comment有一个答案:Git抓紧的文件git mv --force
是 work-tree 副本。这里发生的是Git有很多文件副本!
使用Git进行新提交时,记住几件事很重要。首先,承诺是永久记录。每次提交是或具有:
每个提交的实际名称是一个很大的丑陋的哈希ID,当您(或任何人)进行提交时,Git会在现场将其组成。 Git保证每个大的丑陋哈希ID都是唯一的,以便每个提交都具有不同的哈希ID。完成后,没有人(不是您也不是Git)可以更改一个提交:如果您尝试这样做,并且实际上做了一些更改然后再次提交,那么您得到的是一个不同 >提交,并使用新的和不同的哈希ID。旧提交也保留在存储库中。
在某些情况下,您可以告诉Git 忘记一次提交(实际上是整个提交链),这样您就永远找不到了。最终,Git将清理并删除它们。但是大多数情况下,我们使用Git存储库所做的是添加新的提交,同时保持所有现有的提交不变。我们根本无法更改任何现有的提交,因此一旦完成,它就会保存所有文件的冻结副本,并永久保存,以防您需要将它们从深度冻结中撤回。
由于Git永久(大部分)保存您(或任何人)曾告诉过它的 every 文件的 every 版本,这些文件会迅速占用您的所有文件如果Git只是按原样保存它们,则存储。因此,冻结的文件以特殊的仅Git格式(有时在所有提交中共享共享)被压缩,有时被压缩。新冻结-新提交-只要有可能,只需重用旧提交中的旧冻结即可。这都是自动的,而且是在幕后,但后果很严重。
如果Git无法重新构造/重新水化冻干的文件,您将永远无法将其中的任何退回!不会有git checkout
。简而言之,那将是不好的。因此,Git为您提供了一个空间,可以在其中提取(并解冻)您的文件,然后将它们转换回可用文件。该空间是您的工作树或工作树。
通常,您使用git checkout
告诉Git:我想在这里提交。您使用类似master
的名称 ,但实际上您是通过其唯一的哈希ID选择提交的。 Git会重新构建文件,并将它们放入工作树中,以便您可以访问它们并对其进行处理。
Git会记住您选择的提交(及其分支名称):这是您的当前提交。 Git通过在分支名称上附加名称HEAD
来做到这一点。 1 它将保留您当前的提交,直到您进行某些更改以更改哪个提交即当前的提交为止,包括git checkout
,但还包括进行 new 提交,然后成为当前提交。无论如何,显然,在这一点上,每个文件都有两个副本。如果您有一个名为README.txt
的文件,我们可以将其中一个命名为HEAD:README.txt
,将另一个命名为简单的README.txt
。 HEAD
副本是仅Git的,并且一直冻结,并且工作树副本是正常的。
Git可以在此处停止-它可以将冻结的仅Git的文件永久保存在提交中,以及您正在使用或正在使用的一个工作树副本。但是Git将第三个副本添加到了混合中。
1 将HEAD
附加到某个分支名称足以记住您当前的分支和您的当前提交,因为分支名称会记住该提交。您可以问Git: HEAD
的分支名称是什么?,您会得到分支;或者您可以问Git: HEAD
的提交哈希ID是什么?,然后Git使用分支名称来查找提交。
Git在这里使用了一个技巧,部分是为了提高速度,部分是为了各种其他目的。 Git并没有将文件从深度冻结中取出并进行重构,而忘记了它所做的一切,实际上是将文件从冰箱中复制/复制到一个更方便的位置。在这里,它们仍然以Git的高度压缩形式保存,但是现在它们是未冻结的。
第三个区域(实际上是提交和工作树之间的中间区域 )被分别称为 index , staging area em>或 cache ,具体取决于执行呼叫的是谁/哪一位Git。该索引要做的第一件事是使git commit
快速。由于索引(或暂存区)中的文件始终已经在正确的 form 中,因此git commit
要做的就是冻结它们。其他版本控制系统必须遍历整个工作树,仔细检查每个文件以查看其是否已更改,这甚至可能涉及将文件重新压缩为冻结格式。这需要很长时间。 Git不必这样做。
但这意味着在工作时,每个文件都有一个第三版本。您的工作树HEAD:README.txt
不仅带有README.txt
,而且还有README.txt
的 index 副本,我们可以将其称为:README.txt
在文件上运行git add
时,Git会压缩该文件的工作树版本,并替换之前索引中的版本。或者,如果以前根本不在索引中,那么现在是。无论哪种方式,现在都可以使用文件的新版本了-git commit
要做的就是冻结预压缩的文件!
这是git rm
进入的地方。如果您的文件位于工作树中,因为该文件处于提交状态,则您(或仍然是Git)拥有文件的 3个副本现在,触手可及的文件:当前提交中的HEAD:file
,索引中的:file
和工作树中的file
。运行git rm file
会删除两个 副本:索引中的一个副本和工作树中的一个副本。 (它不能碰到冻结的,因为它已经冻结了!)现在文件不在索引中,它不会在下一个承诺。
但是,如果您运行git rm --cached
,则Git所做的是仅 删除索引副本。现在您有HEAD:file
和file
,但没有:file
。这意味着您进行的下一个提交中将没有文件file
。但是,很难看到您的操作,因为每个文件的索引副本通常是不可见的。如果您使用普通的计算机工具来查看拥有的文件,则会显示工作树文件。
每个文件的HEAD
副本通常也是不可见的,这具有相同的问题-但是由于已提交的文件被冻结,因此我们通常不在乎。如果要查看文件,我们仅使用git checkout
切换到其他提交。这将同时更新索引和工作树,以匹配另一个提交。然后我们可以看一下工作树,因为所有文件的所有三个副本都匹配。
git status
以简短且实用的形式告诉您一切Git从索引中 进行新的提交。因此,索引确定了您将提交的内容。这就是为什么我们可以将其描述为您下一次提交时的结果。但是索引实际上是不可见的。您如何知道下一次提交的内容?
运行git status
是您了解索引情况的方式。
git status
要做的第一件事是告诉您当前分支,即查看特殊名称HEAD
附加到哪个分支名称。这样可以告诉您下一次提交的位置。
git status
的其余输出将告诉您有关准备提交的文件和未准备提交的文件的信息。而不是在索引中列出每个文件(在一个大项目中,文件会是很多文件),git status
首先要做的是比较查看每个文件的副本,以查看自HEAD
副本以来的变化。不需要确切的区别,只需快速扫描索引副本是否是相同,还是不同?(这就是Git的内部冻结格式可以非常快地完成操作。)
如果索引中的文件:file
与HEAD:file
副本不同,则Git会告诉您该文件已暂存为提交< / em>。您知道它将在下一次提交中,但是更有用的是,您也知道在新快照中它将不同。比较旧的(当前HEAD
和建议的新提交,file
将会更改。
同时,git status
还将:file
的索引副本与工作树副本file
进行比较。如果这两个不同,则Git会告诉您该文件未上演提交。这说明您可以立即运行git add
到复制 file
到:file
。
请注意,file
的所有三个版本都可以完全不同!在这种情况下,它是两者 staged for commit
和 not staged for commit
。而且,当然,您可以拥有新文件,这些文件现在不在索引和工作树中的HEAD
中,而却。您可以删除 文件-HEAD
中是,但现在索引和工作树中不是的文件。< / p>
文件的索引和工作树副本是分开的。这意味着您可以在工作树中有一个文件,但在索引中没有。这样的文件是未跟踪的文件。请注意,文件是否在HEAD
提交中无关紧要! (如果在提交HEAD
中是,则必须在索引中 并将其从索引中删除,尚未提交。)运行git status
会告诉您有关此类文件的信息,并抱怨它们未被跟踪。
您还可以在索引中包含文件,但不在工作树中。这是一种有些奇怪的状态,但是如果您使用非Git命令删除文件,则会发生这种情况。 Git并不太在乎您是否已完成此操作-它仍将使用索引副本进行新提交-但git status
会告诉您有关信息:该文件将在index-vs-work-中删除树比较。
您可以通过在*.tmp
文件中列出未跟踪文件的名称(或.gitignore
之类的全局模式)来关闭Git。这不会使文件未跟踪!这只是让Git对他们闭嘴。它也具有其他一些作用,但主要作用是关闭Git。这很有用,因为它使git status
的输出更短了(em)。
git status
仅告诉您您需要了解的信息 –当Git从git diff
运行HEAD
到索引时,有些文件是不同的,还有一些文件当Git从索引到工作树运行git diff
时,文件是不同的,因此git status
变得尽可能有用。您不必有选择地选择其输出来查找有用的东西,因为文件X和Y被暂存,而Z未被暂存正是有用的东西。如果您立即进行下一次提交,则两个文件将不同。如果您git add
,文件Z 也可以不同。
如果仅从索引或仅从工作树中删除文件,则会发现自己处在这些异常情况下。其中有些 do 是有道理的; Git不会阻止任何一个。 Git通常会尝试小心不要遮盖未跟踪的文件,因为与跟踪的文件不同,它们不会永远冻结在新提交中。