为什么 'git mv' 不移动文件?如何让它行动"normally"?
Why does 'git mv' not move a file? How to make it act "normally"?
请原谅我的无知...背景是这样的:我创建了一个TestScritps目录来组织测试脚本。我将三个脚本从 <root dir>
移到了 <root dir>/TestScripts
。我一次移动一个并在每个之后执行本地提交。然后我推送了所有更改。
我到另一台机器上执行拉取:
$ cd cryptopp/
$ git pull
remote: Counting objects: 25, done.
remote: Compressing objects: 100% (24/24), done.
remote: Total 25 (delta 11), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (25/25), done.
From https://github.com/weidai11/cryptopp
2ac9ea1..2a22a84 master -> origin/master
Updating 2ac9ea1..2a22a84
Fast-forward
TestScripts/cryptest-android.sh | 44 +
TestScripts/cryptest-ios.sh | 40 +
TestScripts/cryptest.sh | 5729 +++++++++++++++++++++++++++++++++++++++
rijndael.cpp | 2 +-
setenv-android.sh | 85 +-
5 files changed, 5870 insertions(+), 30 deletions(-)
create mode 100755 TestScripts/cryptest-android.sh
create mode 100755 TestScripts/cryptest-ios.sh
create mode 100755 TestScripts/cryptest.sh
$ ls *.sh
cryptest-android.sh cryptest.sh setenv-android.sh setenv-ios.sh
cryptest-ios.sh rdrand-nasm.sh setenv-embedded.sh
注意文件只是被复制了;他们没有被感动。
我检查了 git-mv
man page,但错误的行为似乎没有被讨论。
我有两个问题。为什么git mv
只复制文件,不移动文件?如何让 git mv
执行 "normally"?在这里,"normally" 意味着几乎每个使用过命令行的人都期望的 - 它将文件从 <target location>
移动到 <destination location>
.
这里是相关的命令历史。
994 rm -rf cryptopp/
995 git clone https://github.com/weidai11/cryptopp
996 cd cryptopp/
997 mkdir TestScripts
998 git mv cryptest.sh TestScripts/
999 ls *.sh
1000 git commit TestScripts/cryptest.sh -m "Organize test scripts (Issue 303)"
1001 ls *.sh
1002 git mv cryptest-ios.sh TestScripts/
1003 git commit TestScripts/cryptest-ios.sh -m "Organize test scripts (Issue 303)"
1004 ls *.sh
1005 git commit
从 git pull
的输出中显示的摘要,我看到那些文件没有被删除。
当你这样做时,例如:
git commit TestScripts/cryptest.sh -m "Organize test scripts (Issue 303)"
虽然 Git 通常很适合跟踪文件移动,但在内部,移动被记录为删除一个文件并创建一个新的相同文件。您提交了 新文件 ,并且 没有 从原始位置删除文件,因此看起来 Git 只是复制了文件.
以后,从 commit
命令中省略文件名通常是个好主意:
git commit -m "Organize test scripts (Issue 303)"
您可以事先 git status
查看将要提交的内容,并根据需要进行修改。
完整的会话可能如下所示:
$ git mv cryptest.sh TestScripts/
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: cryptest.sh -> TestScripts/cryptest.sh
$ git commit -m "Organize test scripts (Issue 303)"
$ git status
On branch master
nothing to commit, working directory clean
$ ls cryptest.sh
ls: cannot access cryptest.sh: No such file or directory
$ ls TestScripts/cryptest.sh
TestScripts/cryptest.sh
要修复,请执行:
git rm cryptes*.sh
git commit
如果您想修复您的历史记录,您可以这样做:
git rebase -i HEAD^3
并将相关提交的命令从 pick
更改为 edit
。在每一站,做:
git rm <file>
git commit --amend
git rebase --continue
其中<file>
为当前原始文件。
请注意,这将重写您的历史记录,因此在机器之间移动时可能会出现问题。
请注意,没有必要删除并重新克隆 Git 存储库,因此如果您将来 运行 遇到麻烦,最好尝试解决根本问题。 (Search around or ask here 如果您需要帮助!)
问题出在您(滥用)git commit
命令的使用上。
git mv
确实移动了文件。比如说,我有一个包含单个文件的回购协议,名为 a
,我想将其移动为 b
:
$ git mv a b
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: a -> b
$ ls
b <-- Only b exists here, no a
移动现在已记录在索引中,但未提交。要创建提交,我这样做:
$ git commit -m "Move a as b"
然而,您所做的是:
$ git commit b -m "Move a as b"
[master b275677] Move a as b
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 b
当您将文件名作为参数提供给 git commit
时,它只包含提交中列出的文件,而不是记录当前索引。
在内部,git 不理解什么是移动。它知道创建了一个文件,并删除了另一个文件。用于显示历史记录的工具(例如 git log
)结合这两条信息并显示文件已移动。但是当你指定commit中只包含新创建的文件时,它并没有记录旧文件的删除,所以当你从另一台机器上拉取时,它不会显示为move。
所以你的问题的答案是:"Why does 'git mv' not move a file? How to make it act “normally”?" - 它确实移动了一个文件,但是你明确告诉git只提交新文件的创建,不是删除旧的。要使其正常运行,请不要这样做 - 相反,发出 git commit
不带文件名作为参数。
请原谅我的无知...背景是这样的:我创建了一个TestScritps目录来组织测试脚本。我将三个脚本从 <root dir>
移到了 <root dir>/TestScripts
。我一次移动一个并在每个之后执行本地提交。然后我推送了所有更改。
我到另一台机器上执行拉取:
$ cd cryptopp/
$ git pull
remote: Counting objects: 25, done.
remote: Compressing objects: 100% (24/24), done.
remote: Total 25 (delta 11), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (25/25), done.
From https://github.com/weidai11/cryptopp
2ac9ea1..2a22a84 master -> origin/master
Updating 2ac9ea1..2a22a84
Fast-forward
TestScripts/cryptest-android.sh | 44 +
TestScripts/cryptest-ios.sh | 40 +
TestScripts/cryptest.sh | 5729 +++++++++++++++++++++++++++++++++++++++
rijndael.cpp | 2 +-
setenv-android.sh | 85 +-
5 files changed, 5870 insertions(+), 30 deletions(-)
create mode 100755 TestScripts/cryptest-android.sh
create mode 100755 TestScripts/cryptest-ios.sh
create mode 100755 TestScripts/cryptest.sh
$ ls *.sh
cryptest-android.sh cryptest.sh setenv-android.sh setenv-ios.sh
cryptest-ios.sh rdrand-nasm.sh setenv-embedded.sh
注意文件只是被复制了;他们没有被感动。
我检查了 git-mv
man page,但错误的行为似乎没有被讨论。
我有两个问题。为什么git mv
只复制文件,不移动文件?如何让 git mv
执行 "normally"?在这里,"normally" 意味着几乎每个使用过命令行的人都期望的 - 它将文件从 <target location>
移动到 <destination location>
.
这里是相关的命令历史。
994 rm -rf cryptopp/
995 git clone https://github.com/weidai11/cryptopp
996 cd cryptopp/
997 mkdir TestScripts
998 git mv cryptest.sh TestScripts/
999 ls *.sh
1000 git commit TestScripts/cryptest.sh -m "Organize test scripts (Issue 303)"
1001 ls *.sh
1002 git mv cryptest-ios.sh TestScripts/
1003 git commit TestScripts/cryptest-ios.sh -m "Organize test scripts (Issue 303)"
1004 ls *.sh
1005 git commit
从 git pull
的输出中显示的摘要,我看到那些文件没有被删除。
当你这样做时,例如:
git commit TestScripts/cryptest.sh -m "Organize test scripts (Issue 303)"
虽然 Git 通常很适合跟踪文件移动,但在内部,移动被记录为删除一个文件并创建一个新的相同文件。您提交了 新文件 ,并且 没有 从原始位置删除文件,因此看起来 Git 只是复制了文件.
以后,从 commit
命令中省略文件名通常是个好主意:
git commit -m "Organize test scripts (Issue 303)"
您可以事先 git status
查看将要提交的内容,并根据需要进行修改。
完整的会话可能如下所示:
$ git mv cryptest.sh TestScripts/
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: cryptest.sh -> TestScripts/cryptest.sh
$ git commit -m "Organize test scripts (Issue 303)"
$ git status
On branch master
nothing to commit, working directory clean
$ ls cryptest.sh
ls: cannot access cryptest.sh: No such file or directory
$ ls TestScripts/cryptest.sh
TestScripts/cryptest.sh
要修复,请执行:
git rm cryptes*.sh
git commit
如果您想修复您的历史记录,您可以这样做:
git rebase -i HEAD^3
并将相关提交的命令从 pick
更改为 edit
。在每一站,做:
git rm <file>
git commit --amend
git rebase --continue
其中<file>
为当前原始文件。
请注意,这将重写您的历史记录,因此在机器之间移动时可能会出现问题。
请注意,没有必要删除并重新克隆 Git 存储库,因此如果您将来 运行 遇到麻烦,最好尝试解决根本问题。 (Search around or ask here 如果您需要帮助!)
问题出在您(滥用)git commit
命令的使用上。
git mv
确实移动了文件。比如说,我有一个包含单个文件的回购协议,名为 a
,我想将其移动为 b
:
$ git mv a b
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: a -> b
$ ls
b <-- Only b exists here, no a
移动现在已记录在索引中,但未提交。要创建提交,我这样做:
$ git commit -m "Move a as b"
然而,您所做的是:
$ git commit b -m "Move a as b"
[master b275677] Move a as b
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 b
当您将文件名作为参数提供给 git commit
时,它只包含提交中列出的文件,而不是记录当前索引。
在内部,git 不理解什么是移动。它知道创建了一个文件,并删除了另一个文件。用于显示历史记录的工具(例如 git log
)结合这两条信息并显示文件已移动。但是当你指定commit中只包含新创建的文件时,它并没有记录旧文件的删除,所以当你从另一台机器上拉取时,它不会显示为move。
所以你的问题的答案是:"Why does 'git mv' not move a file? How to make it act “normally”?" - 它确实移动了一个文件,但是你明确告诉git只提交新文件的创建,不是删除旧的。要使其正常运行,请不要这样做 - 相反,发出 git commit
不带文件名作为参数。