Почему "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-страница, но ошибочное поведение не обсуждается.
У меня два вопроса. Почему git mv
только копировать файлы, а не перемещать их? Как я могу сделать git mv
выполнять "нормально"? Здесь "обычно" означает то, что ожидает почти каждый, кто использовал командную строку - он перемещает файл из <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 ответа
Из резюме, показанного в выводе 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, поэтому, если у вас возникнут проблемы в будущем, лучше попытаться исправить проблему с корнем. ( Поиск вокруг или спросите здесь, если вам нужна помощь!)
Проблема в вашем (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
например) объединить эти две части информации и отобразить файл как перемещенный. Но когда вы указали, что в коммит должен быть включен только вновь созданный файл, он не записал удаление старого файла, поэтому он не отображается как движение при извлечении с другого компьютера.
Итак, ответ на ваш вопрос: "Почему" git mv "не перемещает файл? Как заставить его работать" нормально "?" - он перемещает файл, но вы специально указали git совершать только создание нового файла, а не удаление старого. Чтобы заставить его действовать нормально, не делайте этого - вместо этого, выпустите git commit
без имен файлов в качестве аргументов.