我读过renaming files in git时,您应该提交任何更改,执行重命名,然后暂存重命名的文件。 Git将从内容中识别该文件,而不是将其视为新的未跟踪文件,并保留更改历史记录。
然而,今晚这样做我最终还是回到了git mv
。
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
将Finder中的样式表从iphone.css
重命名为mobile.css
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: css/iphone.css
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# css/mobile.css
所以git现在认为我删除了一个CSS文件,并添加了一个新文件。不是我想要的,让我们撤消重命名,让git完成工作。
> $ git reset HEAD .
Unstaged changes after reset:
M css/iphone.css
M index.html
回到我开始的地方。
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
请改为使用git mv
。
> $ git mv css/iphone.css css/mobile.css
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# renamed: css/iphone.css -> css/mobile.css
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: index.html
#
看起来我们很好。那么为什么当我使用Finder时git第一次没有认识到重命名?
答案 0 :(得分:327)
对于git mv
manual page
说
成功完成后索引会更新, [....]
因此,首先您必须自己更新索引
(使用git add mobile.css
)。然而
git status
仍然会显示两个不同的文件
$ git status
# On branch master
warning: LF will be replaced by CRLF in index.html
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
# new file: mobile.css
#
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: iphone.css
#
您可以通过运行获得不同的输出
git commit --dry-run -a
导致你的结果
预期
Tanascius@H181 /d/temp/blo (master)
$ git commit --dry-run -a
# On branch master
warning: LF will be replaced by CRLF in index.html
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
# renamed: iphone.css -> mobile.css
#
我无法确切地告诉你为什么我们看到这些差异
在git status
和
之间
git commit --dry-run -a
,但是
这是一个提示
Linus
git实际上甚至没有关心整体 内部“重命名检测”,以及您拥有的任何提交 完成重命名完全独立于 然后我们使用启发式来显示重命名。
dry-run
使用真正的重命名机制,而a
git status
可能不会。
答案 1 :(得分:72)
在git将其识别为移动之前,您必须将两个已修改的文件添加到索引中。
mv old new
和git mv old new
之间的唯一区别是git mv还会将文件添加到索引中。
mv old new
然后git add -A
也会奏效。
请注意,您不能只使用git add .
,因为这不会将删除添加到索引中。
答案 2 :(得分:18)
最好的办法是亲自尝试。
mkdir test
cd test
git init
touch aaa.txt
git add .
git commit -a -m "New file"
mv aaa.txt bbb.txt
git add .
git status
git commit --dry-run -a
现在git status和git commit --dry-run -a显示两个不同的结果,其中git status显示bbb.txt作为新文件/ aaa.txt被删除,而--dry-run命令显示实际重命名
~/test$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: bbb.txt
#
# 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: aaa.txt
#
/test$ git commit --dry-run -a
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# renamed: aaa.txt -> bbb.txt
#
现在继续办理登机手续。
git commit -a -m "Rename"
现在您可以看到该文件实际上已重命名,并且git status中显示的内容是错误的。
故事的道德:如果您不确定您的文件是否已重命名,请发出“git commit --dry-run -a”。如果它显示文件已重命名,那么你就可以了。
答案 3 :(得分:10)
你必须git add css/mobile.css
新文件和git rm css/iphone.css
,所以git知道它。那么它将在git status
您可以在状态输出中清楚地看到它(文件的新名称):
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
和(旧名):
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
我认为幕后git mv
只不过是一个包装脚本,它正是这样做的:从索引中删除文件并以不同的名称添加它
答案 4 :(得分:9)
让我们从git角度思考你的文件。
请记住,git不会跟踪有关您文件的任何元数据
您的存储库(以及其他)
$ cd repo
$ ls
...
iphone.css
...
它受git控制:
$ git ls-files --error-unmatch iphone.css &>/dev/null && echo file is tracked
file is tracked
用以下方法测试:
$ touch newfile
$ git ls-files --error-unmatch newfile &>/dev/null && echo file is tracked
(no output, it is not tracked)
$ rm newfile
当你这样做时
$ mv iphone.css mobile.css
从git角度来看,
因此,git建议它已经知道的文件( iphone.css )和它检测到的新文件( mobile.css )但仅当文件在索引或HEAD中时git开始检查他们的内容。
此刻,&#34; iphone.css删除&#34; mobile.css 也不在索引上。
将iphone.css删除添加到索引
$ git rm iphone.css
git告诉你到底发生了什么:( iphone.css 已被删除。没有更多的事情发生了)
然后添加新文件 mobile.css
$ git add mobile.css
这次删除和新文件都在索引上。现在git检测上下文是相同的并将其公开为重命名。事实上,如果文件有50%的相似性,它会将其检测为重命名,这样可以让您稍微更改 mobile.css ,同时将操作保持为重命名。
在git diff
上看到此内容可以重现。既然您的文件在索引上,您必须使用--cached
。稍微修改 mobile.css ,将其添加到索引并查看以下内容之间的区别:
$ git diff --cached
和
$ git diff --cached -M
-M
是&#34;检测重命名&#34; git diff
的选项。 -M
代表-M50%
(50%或更高的相似度会让git将其表示为重命名)但如果您编辑mobile.css,可以将其减少到-M20%
(20%)
答案 5 :(得分:9)
对于git 1.7.x,以下命令对我有用:
git mv css/iphone.css css/mobile.css
git commit -m 'Rename folder.'
不需要git add,因为原始文件(即css / mobile.css)之前已经在提交的文件中。
答案 6 :(得分:7)
Git会识别内容中的文件,而不是将其视为新的未跟踪文件
那是你出错的地方。
只有在之后添加文件,git才能从内容中识别它。
答案 7 :(得分:7)
步骤1:将文件从oldfile重命名为newfile
git mv #oldfile #newfile
Step2:git commit并添加评论
git commit -m "rename oldfile to newfile"
步骤3:将此更改推送到远程服务器
git push origin #localbranch:#remotebranch
答案 8 :(得分:3)
您没有登台查找结果。我相信如果你通过Finder进行了移动然后做了git add css/mobile.css ; git rm css/iphone.css
,git会计算新文件的哈希值,然后才会意识到文件的哈希值匹配(因此它是重命名)。
答案 9 :(得分:2)
如果您确实需要手动重命名文件,例如。使用脚本批量重命名一堆文件,然后使用git add -A .
为我工作。
答案 10 :(得分:1)
对于Xcode用户:如果您在Xcode中重命名文件,则会看到徽章图标更改为附加。如果使用XCode进行提交,您实际上将创建一个新文件并丢失历史记录。
解决方法很简单,但在使用Xcode提交之前必须这样做:
重命名:Project / OldName.h - &gt;项目/ NewName.h 重命名:Project / OldName.m - &gt;项目/ NewName.m
然后返回XCode,您将看到徽章从A更改为M并保存,以便现在使用xcode进行更改。
答案 11 :(得分:0)
刚遇到这个问题-如果您更新了一堆文件并且不想全部git mv
,那么这也可行:
/dir/RenamedFile.js
重命名为/whatever/RenamedFile.js
。git add -A
进行更改/dir/RenamedFile.js
。git add -A
将再次重新执行该更改,并强制git选择文件名更改。