- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个已重命名然后编辑的文件。我想告诉 Git 进行重命名,而不是内容修改。也就是说,我希望分阶段删除旧文件名,并使用新文件名添加旧文件内容。
所以我有这个:
Changes not staged for commit:
deleted: old-name.txt
Untracked files:
new-name.txt
Changes to be committed:
new file: new-name.txt
deleted: old-name.txt
Changes not staged for commit:
modified: new-name.txt
Changes to be committed:
renamed: old-name.txt -> new-name.txt
Changes not staged for commit:
modified: new-name.txt
git rm
,没问题:
$ git rm old-name.txt
mv
在 shell 中,
git add
,然后恢复新内容,但这似乎是很长的路要走!)
最佳答案
Git 并没有真正进行重命名。它们都是以“事后”的方式计算的:git 将一个提交与另一个提交进行比较,并在比较时决定是否有重命名。这意味着 git 是否考虑“重命名”是动态变化的。我知道你在问一个你甚至还没有做出的提交,但请耐心等待,这确实是相关的(但答案会很长)。
当您询问 git(通过 git show
或 git log -p
或 git diff HEAD^ HEAD
)“上次提交中发生了什么”时,它会运行上一次提交的差异(HEAD^
或 HEAD~1
或实际原始 SHA-1对于之前的提交——任何这些都可以识别它)和当前的提交( HEAD
)。在进行这种差异时,它可能会发现曾经有一个 old.txt
并且不再存在;并且没有 new.txt
但现在有。
这些文件名——曾经存在但不存在的文件,以及现在存在但不存在的文件——被放入标记为“重命名候选者”的堆中。然后,对于堆中的每个名称,git 比较“旧内容”和“新内容”。由于 git 将内容减少到 SHA-1 的方式,精确匹配的比较非常容易;如果精确匹配失败,git 会切换到可选的“内容至少相似”差异以检查重命名。与 git diff
此可选步骤由 -M
控制旗帜。对于其他命令,它要么由您的 git config
设置值,或硬编码到命令中。
现在,回到集结区和 git status
:git 在索引/暂存区中存储的内容基本上是“下一次提交的原型(prototype)”。当您git add
git 立即存储文件内容,在此过程中计算 SHA-1,然后将 SHA-1 存储在索引中。当您git rm
有些东西,git 在索引中存储了一个注释,说“这个路径名在下一次提交时被故意删除”。git status
命令,然后,简单地做一个差异——或者实际上,两个差异:HEAD
vs 索引,用于将要提交的内容;和索引与工作树,对于可能(但尚未)提交的内容。
在第一个差异中,git 使用与以往相同的机制来检测重命名。如果 HEAD
中有路径提交在索引中消失了,并且索引中的路径是新的而不是在 HEAD
中提交,它是重命名检测的候选者。 git status
命令硬连线将检测重命名为“on”(文件计数限制为 200;只有一个重命名检测候选者,这个限制就足够了)。
这对您的案件意味着什么?好吧,您重命名了一个文件(不使用 git mv
,但这并不重要,因为 git status
在 git status
找到重命名或找不到它),现在有了更新的不同版本新文件。
如果您 git add
新版本,新版本进入 repo,其 SHA-1 在索引中,当 git status
做一个差异,它将比较新旧。如果它们至少“50% 相似”( git status
的硬接线值),git 会告诉您文件已重命名。
当然,git add
-ing 修改后的内容并不是你所要求的:你想做一个中间提交,其中文件只被重命名,即提交带有新名称但旧内容的树。
由于上述所有动态重命名检测,您不必这样做。如果你想这样做(无论出于何种原因)......好吧,git 并没有让这一切变得那么容易。
最直接的方法就像你建议的那样:将修改后的内容移到某处,使用 git checkout -- old-name.txt
,然后 git mv old-name.txt new-name.txt
,然后提交。 git mv
将重命名索引/暂存区域中的文件,并重命名工作树版本。
如 git mv
有一个 --cached
选项如 git rm
是的,你可以只是 git mv --cached old-name.txt new-name.txt
然后 git commit
.第一步将重命名索引中的文件,而不触及工作树。但它没有:它坚持覆盖工作树版本,并且坚持旧名称必须存在于工作树中才能启动。
在不触及工作树的情况下执行此操作的单步方法是使用 git update-index --index-info
,但这也有点乱(反正我马上就会展示)。幸运的是,我们还能做最后一件事。我已经设置了与您相同的情况,通过将旧名称重命名为新名称并修改文件:
$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: old-name.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
new-name.txt
git mv
再次切换到新名称 :
$ mv new-name.txt old-name.txt
$ git mv old-name.txt new-name.txt
git mv
更新索引中的名称,但将原始内容保留为索引 SHA-1,但将工作树版本(新内容)移动到工作树中:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: old-name.txt -> new-name.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: new-name.txt
git commit
使用重命名而不是新内容进行提交。
git update-index
怎么样? ?好吧,首先让我们回到“在工作树中更改,索引匹配 HEAD 提交”状态:
$ git reset --mixed HEAD # set index=HEAD, leave work-tree alone
old-name.txt
的索引中有什么内容:
$ git ls-files --stage -- old-name.txt
100644 2b27f2df63a3419da26984b5f7bafa29bdf5b3e3 0 old-name.txt
git update-index --index-info
要做的就是清除
old-name.txt
的条目但为
new-name.txt
创建一个相同的条目:
$ (git ls-files --stage -- old-name.txt;
git ls-files --stage -- old-name.txt) |
sed -e \
'1s/^[0-9]* [0-9a-f]*/000000 0000000000000000000000000000000000000000/' \
-e '2s/old-name.txt$/new-name.txt/' |
git update-index --index-info
sed
命令。第一个替换更改文件模式(100644,但任何模式都会变成全零)和 SHA-1(匹配任何 SHA-1,替换为 git 的特殊全零 SHA-1),第二个离开模式并替换名称时单独使用 SHA-1。
old-name.txt
的未 merge 条目,这可能会严重失败。因为文件可能还有其他阶段(1 到 3)。
关于git - 如何在 git 中不进行后续编辑的情况下进行重命名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29706086/
我时不时地输入“git”,然后想到别的东西,然后输入例如“git checkout master”。当然,这给我留下了 $ git git checkout master git: 'git' is
我做到了 git 克隆 git://foo.git 光盘富 ...编辑文件.. 现在我想重新开始。我不在乎我已经做出的任何改变,但我不想再次克隆整个巨型 foo.git,只是丢失我所有的更改。我怎
我在我的电脑上开发代码,我的计算节点很少。 为了让我的程序保持同步,我决定使用 git。以前,我以一种单向模式使用它来“下推”从 PC 到计算节点的更改。但是时不时遇到计算节点特有的小bug,现场修复
虽然它似乎什么也没做,但它没有给出任何警告或错误消息。有什么想法吗? 最佳答案 来自 Git 源的注释: /* * Read a directory tree. We currently ignor
我知道如何为这样的 HTTPS 请求提供用户名和密码: git clone https://username:password@remote 但我想知道如何像这样向 Remote 提供用户名和密码:
Git GUI、Git Bash 和 Git CMD 之间有什么区别?我是初学者,为了进行安装,我发现自己通常同时使用 git bash 和 git CMD 最佳答案 Git CMD 就像使用 git
有人能告诉我git中文件索引被删除是什么意思吗?这些文件在我的 VS Code 中标记为红色,但我仍然可以修改文件并将更改推送到将反射(reflect)这些更改的远程存储库。我认为这一切都是在我使用命
我通过 git 子树将 GLFV 库添加到项目中,但出现此警告“看起来您的 git 安装或您的 git-subtree 安装已损坏”。还描述了几个原因,为什么这可能是: 如 git --exec-pa
我有需要外部 git 项目的 repo,但我不想使用子模块,因为我想在 github 上存档所有文件,所以我认为我只是将具有 git repo 的整个目录添加到 git 但它不t 添加里面的 .git
我有需要外部 git 项目的 repo,但我不想使用子模块,因为我想在 github 上存档所有文件,所以我认为我只是将具有 git repo 的整个目录添加到 git 但它不t 添加里面的 .git
我一直在阅读一篇文章,作者在其中指示:在现有存储库中创建一个新存储库,并想知道这是否是他忽略的错误。稍后我会与他核实。 这些是我要检查的条件: 将现有目录制作成仓库的条件,并且已经 checkin 主
我确实在不同的计算机上处理相同的项目,我想知道是否有一种方法可以跟踪该 .git 文件夹,这样我就不必在所有本地文件中重新配置配置文件。 我将所有工作推送到 bitbucket。 最佳答案 不,没
这个问题在这里已经有了答案: How does git store files? (3 个答案) 关闭 9 年前。 我为我的许多项目创建了一个远程存储库,所以它是我的push 的目的地。与 git
应该如何在 git 中查看文件内容的完整历史记录? 一个文件在 git 中的历史很短,存储库通过 git-svn 同步,但在 svn 中的历史很长。 git 中的历史记录到达文件移动的位置。要查看历史
我是confused here ... 如何对修改后的文件进行git commit,以及如何对新文件进行git commit? 还有,你如何在git中单独提交文件? 最佳答案 git 提交过程分为两个
正在搜索 throw SO 来寻找答案。遇到这个似乎没有给出任何答案的旧线程。重新触发此线程,希望有人知道! 有人能告诉我 git subtree 和 git filter-branch 的区别吗?为
我想知道是否有一种方法可以避免在每个 Git 命令的开头键入单词 git。 如果有一种方法可以在打开命令提示符进入 “Git 模式” 后只使用一次 git 命令就好了。 例如: git> 之后,我们键
当您修改工作目录中的文件时,git 会告诉您使用“git add”暂存。 当您向工作目录添加新文件时,git 会告诉您使用“git add”开始跟踪。 我对这两个概念有点困惑,因为我假设跟踪文件的更改
为什么 git://有效 $ git clone git://github.com/schacon/grit.git Cloning into 'grit'... ... Checking conne
我在以下沙箱中练习 git:https://learngitbranching.js.org/?NODEMO 我在两个单独的 session 中运行了两组命令。第一组命令顺序如下: git clone
我是一名优秀的程序员,十分优秀!