奇怪的 `git mv` 行为
Odd `git mv` behaviour
上个月,我开始为 GitHub 存储库做出贡献,方法是分叉相应的存储库,创建功能 b运行ch,然后提交拉取请求。在重复该过程几天时,我 运行 在使用预安装的 Linux 命令 mv
和 Git 命令重命名文件时遇到了一个奇怪的问题 git mv
.
实际的问题是,这取决于您何时 move/rename 一个带有 git mv
的文件,何时 git add
它以及您在什么时候编辑重命名的文件,您要么得到:
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: somethingelse -> something
或者这样:
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: something
deleted: somethingelse
为了证明这一点,我写了一个 test:
#!/bin/bash
# To my knowledge, this “problem” only occurs with new files in a Git repo
printf "COMMAND: mkdir -v gitrepo\n\n"
mkdir -v gitrepo
printf "\nCOMMAND: cd gitrepo\n\n"
cd gitrepo
printf "\nCOMMAND: git init\n\n"
git init
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: touch something\n\n"
touch something
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: git add something\n\n"
git add something
printf "\nCOMMAND: git status\n\n"
git status
printf '\nCOMMAND: git commit -m "Added something"\n\n'
git commit -m "Added something"
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: git mv something somethingelse\n\n"
git mv something somethingelse
printf "\nCOMMAND: git status\n\n"
git status
# Type in the following on line 1: First line of code
printf "\nCOMMAND: vim somethingelse\n\n"
vim somethingelse
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: git add somethingelse\n\n"
git add somethingelse
printf "\nCOMMAND: git status\n\n"
git status
printf '\nCOMMAND: git commit -m "Renamed something to somethingelse and edited somethingelse"\n\n'
git commit -m "Renamed something to somethingelse and edited somethingelse"
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: git mv somethingelse something\n\n"
git mv somethingelse something
printf "\nCOMMAND: git status\n\n"
git status
# If you add something to the first line, the rename will not be detected by Git
# However, if you instead create 2 newlines and fill line 3 with new code,
# the rename gets detected for whatever reason
printf "\nCOMMAND: vim something\n\n"
vim something
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: git add something\n\n"
git add something
printf "\nCOMMAND: git status\n\n"
git status
printf '\nCOMMAND: git commit -m "Renamed somethingelse to something and edited something"\n\n'
git commit -m "Renamed somethingelse to something and edited something"
printf "\nCOMMAND: git status\n\n"
git status
cd .. && rm -fr gitrepo && printf "\nREMOVED gitrepo folder\n"
printf "\nDONE.\n"
出于某种原因,这主要影响“新文件”,而不是存储库中已经存在的文件。例如,如果您使用 git clone https://github.com/christianheinrichs/Spoon-Knife.git
克隆我的 Spoon-Knife repository 分支,然后应用链接测试脚本的工作流程,您会发现在大多数情况下您将能够重命名 README.md 文件到自述文件,编辑它,它仍然算作重命名而不是新的 file/deleted 拆分。
虽然我可以在克隆的 Spoon-Knife fork 存储库上重现新的 file/deleted 行为,但我不确定我是怎么做到的,请相信我,当我说我试图弄清楚它时。
那么这里到底发生了什么我不明白的事情?
参见:https://gist.github.com/christianheinrichs/e50bfdd5eec70a606fa6ce4a88c5951b#file-git_mv-test-sh-L65
git
不保留标志说 "this newname
file was initially called oldname
file" :
git mv oldname newname
# is exactly equivalent to :
mv oldname newname
git rm oldname
git add newname
显示文件的状态时,git
会尝试通过比较文件的内容并查看它们的相似程度来猜测它是 rename
还是 delete + add
是。
所以 : 如果您从 git mv
一个文件开始,然后编辑该文件,根据文件修改的程度,git 可能会或可能不会看到所有内容以 mv
.
开头
另请参阅此问题的答案:
上个月,我开始为 GitHub 存储库做出贡献,方法是分叉相应的存储库,创建功能 b运行ch,然后提交拉取请求。在重复该过程几天时,我 运行 在使用预安装的 Linux 命令 mv
和 Git 命令重命名文件时遇到了一个奇怪的问题 git mv
.
实际的问题是,这取决于您何时 move/rename 一个带有 git mv
的文件,何时 git add
它以及您在什么时候编辑重命名的文件,您要么得到:
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: somethingelse -> something
或者这样:
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: something
deleted: somethingelse
为了证明这一点,我写了一个 test:
#!/bin/bash
# To my knowledge, this “problem” only occurs with new files in a Git repo
printf "COMMAND: mkdir -v gitrepo\n\n"
mkdir -v gitrepo
printf "\nCOMMAND: cd gitrepo\n\n"
cd gitrepo
printf "\nCOMMAND: git init\n\n"
git init
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: touch something\n\n"
touch something
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: git add something\n\n"
git add something
printf "\nCOMMAND: git status\n\n"
git status
printf '\nCOMMAND: git commit -m "Added something"\n\n'
git commit -m "Added something"
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: git mv something somethingelse\n\n"
git mv something somethingelse
printf "\nCOMMAND: git status\n\n"
git status
# Type in the following on line 1: First line of code
printf "\nCOMMAND: vim somethingelse\n\n"
vim somethingelse
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: git add somethingelse\n\n"
git add somethingelse
printf "\nCOMMAND: git status\n\n"
git status
printf '\nCOMMAND: git commit -m "Renamed something to somethingelse and edited somethingelse"\n\n'
git commit -m "Renamed something to somethingelse and edited somethingelse"
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: git mv somethingelse something\n\n"
git mv somethingelse something
printf "\nCOMMAND: git status\n\n"
git status
# If you add something to the first line, the rename will not be detected by Git
# However, if you instead create 2 newlines and fill line 3 with new code,
# the rename gets detected for whatever reason
printf "\nCOMMAND: vim something\n\n"
vim something
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: git add something\n\n"
git add something
printf "\nCOMMAND: git status\n\n"
git status
printf '\nCOMMAND: git commit -m "Renamed somethingelse to something and edited something"\n\n'
git commit -m "Renamed somethingelse to something and edited something"
printf "\nCOMMAND: git status\n\n"
git status
cd .. && rm -fr gitrepo && printf "\nREMOVED gitrepo folder\n"
printf "\nDONE.\n"
出于某种原因,这主要影响“新文件”,而不是存储库中已经存在的文件。例如,如果您使用 git clone https://github.com/christianheinrichs/Spoon-Knife.git
克隆我的 Spoon-Knife repository 分支,然后应用链接测试脚本的工作流程,您会发现在大多数情况下您将能够重命名 README.md 文件到自述文件,编辑它,它仍然算作重命名而不是新的 file/deleted 拆分。
虽然我可以在克隆的 Spoon-Knife fork 存储库上重现新的 file/deleted 行为,但我不确定我是怎么做到的,请相信我,当我说我试图弄清楚它时。
那么这里到底发生了什么我不明白的事情?
参见:https://gist.github.com/christianheinrichs/e50bfdd5eec70a606fa6ce4a88c5951b#file-git_mv-test-sh-L65
git
不保留标志说 "this newname
file was initially called oldname
file" :
git mv oldname newname
# is exactly equivalent to :
mv oldname newname
git rm oldname
git add newname
显示文件的状态时,git
会尝试通过比较文件的内容并查看它们的相似程度来猜测它是 rename
还是 delete + add
是。
所以 : 如果您从 git mv
一个文件开始,然后编辑该文件,根据文件修改的程度,git 可能会或可能不会看到所有内容以 mv
.
另请参阅此问题的答案: