[英]File rename failed in remote git repository
我又迷失了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),目的地=路径/到/ Dockerfile
这阻止了我重命名该文件,因为存在另一个同名文件。 我设法使用以下方法重命名了文件:
git mv --force "path/to/Dockerfile (local_model)" "path/to/Dockerfile"
毕竟(以及稍后还要应用commit ...
和push..
),但我感到困惑。
与目标文件同名的文件在哪里? 我知道此命令仅影响远程存储库,因此与本地存储库不应有任何冲突,对吗?
eftshift0的评论有一个答案:Git 抓紧的文件git mv --force
覆盖了,是工作树副本。 这里发生的是Git有很多文件副本!
当您使用Git进行新提交时,记住几件事很重要。 首先, 提交本身就是永久记录。 每个提交是或具有:
每个提交的实际名称都是一个很大的丑陋的哈希ID,当您(或任何人)进行提交时,Git会在现场将其组成。 Git保证每个大的丑陋哈希ID都是唯一的,以便每个提交都具有不同的哈希ID。 一旦完成,就没有人(您或Git)都无法更改提交:如果您尝试执行此操作,并且实际上确实进行了更改并再次提交,则您得到的是具有新的和不同的哈希ID的不同提交。 旧的提交也保留在存储库中。
在某些情况下,你可以告诉Git的有关承诺(实际上,所有提交的整个链条),这样就可以再也找不到他们忘记 ; 最终,Git将清理并删除它们。 但是大多数情况下,我们使用Git存储库所做的是添加新的commits ,同时保持所有现有的committ不变。 我们根本无法更改任何现有的提交,因此一旦完成,它将拥有所有文件的冻结副本,并永久保存,以防万一您需要将它们从深度冻结中撤回。
因为Git会永久(大部分)保存您(或任何人)曾要求保存的每个文件的每个版本,所以如果Git照原样保存,这些文件将迅速占用您的所有存储空间。 因此,冻结的文件以特殊的仅Git格式被压缩,有时被压缩,在所有提交之间共享 。 新冻结-新提交-只要有可能,只需重用旧提交中的旧冻结即可。 这都是自动的,而且是在幕后,但后果很严重。
如果Git的没有办法重建/重新滋润你冻干文件,你就永远无法得到任何人的回应! 没有git checkout
。 简而言之,那将是不好的。 因此,Git为您提供了一个空间,可以在其中提取(并解冻)您的文件,然后将它们转换回可用文件。 这个空间是您的工作树或工作树 。
通常,您使用git checkout
告诉Git: 我想在这里提交。 您使用的名称类似于master
,但实际上是通过其唯一的哈希ID选择提交。 Git重构文件并将其放入您的工作树中,以便您可以访问它们并对其进行处理。
Git会记住您选择的提交(及其分支名称):这是您当前的提交 。 Git通过将名称HEAD
附加到分支名称来做到这一点。 1它一直是您的当前提交,直到您执行某些更改来更改哪个提交才是当前提交为止,包括git checkout
,还包括进行一个新提交,然后该提交成为当前提交。 无论如何,显然,在这一点上,每个文件都有两个副本。 如果您有一个名为README.txt
的文件,我们可以将其中一个称为HEAD:README.txt
,将另一个命名为纯README.txt
。 HEAD
副本是仅Git的,并且一直冻结,并且工作树副本是正常的。
Git可以在此处停止-它可以将冻结的仅Git的文件永久保存在提交中,再加上您正在使用或使用的一个工作树副本。 但是Git将第三个副本添加到混合中。
1将HEAD
附加到某个分支名称就足以记住当前分支和当前提交,因为分支名称会记住提交。 您可以询问Git: HEAD
的分支名称是什么? 然后你得到了分支; 或者您可以问Git: HEAD
的提交哈希ID是什么? 然后,Git使用分支名称来查找提交。
Git在这里使用了一个技巧,部分是为了提高速度,部分是为了各种其他目的。 Git并没有将文件从深度冻结中取出来进行重构,而忘记了所做的事情,而是将文件从冰箱中复制到更方便的位置。 在这里,它们仍然保持为Git的高度压缩形式,但是现在它们已经解冻了 。
第三个区域(实际上是提交和工作树之间的中间区域)被称为index , 登台区域或缓存 ,具体取决于Git的执行者是谁。 该索引要做的第一件事是它使git commit
快速 。 由于索引(或暂存区域)中的文件始终已经具有正确的格式 ,因此所有git commit
要做的就是冻结它们。 其他版本控制系统必须遍历整个工作树,仔细检查每个文件以查看其是否已更改,这甚至可能涉及将文件重新压缩为冻结格式。 这需要很长时间。 Git不必这样做。
但这意味着在工作时,每个文件都有第三个版本。 不仅是有一个HEAD:README.txt
去与你的工作树README.txt
,还有的指数复制README.txt
,我们可以称之为:README.txt
。
在文件上运行git add
时,Git会压缩该文件的工作树版本,并替换之前索引中的版本。 或者,如果以前根本不在索引中,那么现在是。 无论哪种方式,现在都可以使用文件的新版本git commit
要做的就是冻结预压缩的文件!
这就是git rm
进入的地方。如果您有一个文件因为在提交中而在工作树中,那么您(或无论如何还是Git)现在都唾手可得该文件的三个副本 : HEAD:file
当前HEAD:file
提交, :file
在索引中和file
在工作树中。 运行git rm file
会删除两个副本:索引中的一个副本和工作树中的一个副本。 (它不能被冻结,因为它被冻结了!)既然文件不在索引中,那么它将不在您进行的下一次提交中。
如果你运行git rm --cached
,不过,什么混帐做的是只删除索引副本。 现在您有了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会告诉你,这个文件上演提交 。 您知道它将在下一次提交中,但更有用的是,您还知道新快照中的它将有所不同 。 比较旧的(当前HEAD
)和建议的新提交, file
将已更改 。
同时, git status
还将:file
的索引副本与工作树副本file
。 如果这两个不同,则Git会告诉您该文件未暂存为commit 。 这告诉您可以立即运行git add
将 file
复制到:file
。
请注意,您可以使file
所有三个版本都不同! 在这种情况下, 它既 staged for commit
,也可以 not staged for commit
。 而且,当然,您可以拥有新文件-这些文件不在HEAD
,但现在在索引和工作树中。 您可以删除的文件,文件是 HEAD
,但不是在索引和工作树了。
文件的索引和工作树副本是分开的内容。 这意味着您可以在工作树中有一个文件,但在索引中没有。 这样的文件是未跟踪的文件 。 请注意,文件是否在HEAD
提交中都没有关系! (如果是在HEAD
承诺,它必须是,这是该指数的情况下,你已经从索引中删除它,只是还没有提交。)运行git status
会告诉你这样的文件,抱怨他们没有被追踪。
您还可以在索引中包含文件,但不在工作树中。 这是一种有些奇怪的状态,但是如果您使用非Git命令删除文件,则会发生这种情况。 Git并不太在乎您是否已完成此操作-它仍将索引副本用于新提交-但git status
会告诉您有关信息:该文件将在index-vs-work-tree比较中删除。
您可以通过在.gitignore
文件中列出未跟踪文件的名称(或*.tmp
类的glob模式 )来关闭Git。 这不会使文件无法跟踪! 这只是让Git对他们闭嘴。 它也具有其他一些作用,但主要作用是关闭Git。 这很有用,因为它使git status
输出更短 。
当git status
告诉你,你只需要知道的内容 -即某些文件是不同的,当Git的运行git diff
从HEAD
索引,有些文件是不同的,当Git的运行git diff
从指标的工作树,然后git status
变得尽可能有用。 您不必有选择地选择其输出来查找有用的东西,因为文件X和Y已暂存,而Z未被暂存恰恰是有用的东西。 如果您立即进行下一次提交,则两个文件将不同。 如果您git add
,文件Z 也可能会不同。
如果仅从索引或仅从工作树中选择性地删除文件,则会发现自己处在这些异常情况下。 其中一些确实有道理; Git不会阻止任何一个。 Git通常会尝试小心不要遮盖未跟踪的文件,因为与被跟踪的文件不同,它们不会永远冻结在新提交中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.