繁体   English   中英

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

[英]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进行新提交时,记住几件事很重要。 首先, 提交本身就是永久记录。 每个提交是或具有:

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

每个提交的实际名称都是一个很大的丑陋的哈希ID,当您(或任何人)进行提交时,Git会在现场将其组成。 Git保证每个大的丑陋哈希ID都是唯一的,以便每个提交都具有不同的哈希ID。 一旦完成,就没有人(您或Git)都无法更改提交:如果您尝试执行此操作,并且实际上确实进行了更改并再次提交,则您得到的是具有新的和不同的哈希ID的不同提交。 旧的提交也保留在存储库中。

在某些情况下,你可以告诉Git的有关承诺(实际上,所有提交的整个链条),这样就可以再也找不到他们忘记 ; 最终,Git将清理并删除它们。 但是大多数情况下,我们使用Git存储库所做的是添加新的commits ,同时保持所有现有的committ不变。 我们根本无法更改任何现有的提交,因此一旦完成,它将拥有所有文件的冻结副本,并永久保存,以防万一您需要将它们从深度冻结中撤回。

冻结的文件被压缩且仅支持Git,因此我们必须有一个工作树

因为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将第三个副本添加到混合中。


1HEAD附加到某个分支名称就足以记住当前分支当前提交,因为分支名称会记住提交。 您可以询问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:filefile但是没有: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 diffHEAD索引,有些文件是不同的,当Git的运行git diff从指标的工作树,然后git status变得尽可能有用。 您不必有选择地选择其输出来查找有用的东西,因为文件X和Y已暂存,而Z未被暂存恰恰是有用的东西。 如果您立即进行下一次提交,则两个文件将不同。 如果您git add ,文件Z 也可能会不同。

如果仅从索引或仅从工作树中选择性地删除文件,则会发现自己处在这些异常情况下。 其中一些确实有道理; Git不会阻止任何一个。 Git通常会尝试小心不要遮盖未跟踪的文件,因为与被跟踪的文件不同,它们不会永远冻结在新提交中。

暂无
暂无

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

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