远程git存储库中的文件重命名失败

时间:2018-09-28 12:59:50

标签: git

我又迷失了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..),但我感到困惑。

与目标文件同名的文件在哪里?我知道此命令仅影响远程存储库,因此与本地存储库不应有任何冲突,对吧?

1 个答案:

答案 0 :(得分:2)

eftshift0's comment有一个答案:Git抓紧的文件git mv --force work-tree 副本。这里发生的是Git有很多文件副本!

提交是永久的(主要是)并且是只读的,并且永久冻结文件

使用Git进行新提交时,记住几件事很重要。首先,承诺是永久记录。每次提交是或具有:

  • 您告诉Git冻结到该提交中的所有文件的快照;
  • 您的姓名(作为作者和提交者),或者如果提交是其他人提交的,则为作者/提交者的名字;
  • 您(或其他人)的日志消息有关您为什么进行提交的信息;并且-这部分很关键,但是由于我们不关心Git的历史如何-提交者的父母的哈希ID 而在这里不作介绍。

每个提交的实际名称是一个很大的丑陋的哈希ID,当您(或任何人)进行提交时,Git会在现场将其组成。 Git保证每个大的丑陋哈希ID都是唯一的,以便每个提交都具有不同的哈希ID。完成后,没有人(不是您也不是Git)可以更改一个提交:如果您尝试这样做,并且实际上做了一些更改然后再次提交,那么您得到的是一个不同 >提交,并使用新的和不同的哈希ID。旧提交也保留在存储库中。

在某些情况下,您可以告诉Git 忘记一次提交(实际上是整个提交链),这样您就永远找不到了。最终,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.txtHEAD副本是仅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:filefile,但没有:file。这意味着您进行的下一个提交中将没有文件file。但是,很难看到您的操作,因为每个文件的索引副本通常是不可见的。如果您使用普通的计算机工具来查看拥有的文件,则会显示工作树文件。

每个文件的HEAD副本通常也是不可见的,这具有相同的问题-但是由于已提交的文件被冻结,因此我们通常不在乎。如果要查看文件,我们仅使用git checkout切换到其他提交。这将同时更新索引和工作树,以匹配另一个提交。然后我们可以看一下工作树,因为所有文件的所有三个副本都匹配。

git status以简短且实用的形式告诉您一切

Git从索引中 进行新的提交。因此,索引确定了您将提交的内容。这就是为什么我们可以将其描述为您下一次提交时的结果。但是索引实际上是不可见的。您如何知道下一次提交的内容?

运行git status是您了解索引情况的方式。

git status要做的第一件事是告诉您当前分支,即查看特殊名称HEAD附加到哪个分支名称。这样可以告诉您下一次提交的位置。

git status的其余输出将告诉您有关准备提交的文件未准备提交的文件的信息。而不是在索引中列出每个文件(在一个大项目中,文件会是很多文件),git status首先要做的是比较查看每个文件的副本,以查看自HEAD副本以来的变化。不需要确切的区别,只需快速扫描索引副本是否是相同,还是不同(这就是Git的内部冻结格式可以非常快地完成操作。)

如果索引中的文件:fileHEAD: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通常会尝试小心不要遮盖未跟踪的文件,因为与跟踪的文件不同,它们不会永远冻结在新提交中。