为什么' git mv'不移动文件?如何使其行动"通常"?

时间:2016-09-23 17:50:11

标签: git git-mv

请原谅我的无知......以下是背景:我创建了一个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正常表现&#34;&#34;?在这里,&#34;通常&#34;表示几乎每个使用命令行的人都希望 - 它将文件从<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

2 个答案:

答案 0 :(得分:3)

根据git commit TestScripts/cryptest.sh -m "Organize test scripts (Issue 303)" 输出中显示的摘要,我发现这些文件未被删除。

当你这样做时:

commit

虽然Git通常很好地跟踪文件移动,但内部移动被记录为删除一个文件并创建一个新的相同文件。您从原始位置提交了新文件文件删除,因此看起来Git只是复制了该文件。

将来,从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>

{{1}}是当前原始文件。

请注意,这会重写您的历史记录,因此在机器之间移动时可能会出现问题。

请注意,没有必要删除并重新克隆Git仓库,因此如果您将来遇到麻烦,最好尝试修复根问题。 (Search aroundask here如果您需要帮助!)

答案 1 :(得分:2)

问题在于你(ab)使用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)将这两个信息组合在一起,并将文件显示为已移动。但是当你指定只有新创建的文件应该包含在提交中时,它没有记录旧文件的删除,因此当你从另一台机器上拔出时它不会显示为移动。

所以问题的答案是:&#34;为什么&#39; git mv&#39;不移动文件?如何让它“正常”行事?&#34; - 它会移动一个文件,但你明确告诉git只提交新文件的创建,而不是删除旧文件。为了使其正常行事,请不要这样做 - 而是在没有文件名作为参数的情况下发出git commit