Обработка переименований файлов в git
Я читал, что при переименовании файлов в 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?
Ответы
Ответ 1
Для git mv
страница руководства
говорит
Индекс обновляется после успешного завершения, [....]
Итак, сначала вам нужно обновить индекс самостоятельно
(используя 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
, что приводит к тому, что вы
ожидать
[email protected] /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
, но
вот подсказка от
Линус
git действительно даже не заботится обо всем "переименовать обнаружение" внутренне, и любые фиксации у вас есть сделанные с переименованиями, полностью независимы от эвристики, которые мы используем для отображения переименований.
A dry-run
использует реальные механизмы переименования, в то время как
git status
, вероятно, нет.
Ответ 2
Вы должны добавить два измененных файла в индекс до того, как git распознает его как перемещение.
Единственное различие между mv old new
и git mv old new
заключается в том, что git mv также добавляет файлы в индекс.
mv old new
, тогда git add -A
тоже работал бы.
Обратите внимание, что вы не можете просто использовать git add .
, потому что это не добавляет удаления в индекс.
См. Разница между "git add -A" и "git добавить" .
Ответ 3
Лучше всего попробовать это для себя.
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 и git commit -dry-run -a показывает два разных результата, где git status показывает bbb.txt, когда новый файл /aaa.txt удаляется, а -dry- команды запуска показывают фактическое переименование.
~/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, является неправильным.
Мораль истории: если вы не уверены, переименован ли ваш файл, выполните команду "git commit -dry-run -a". Если он показывает, что файл переименован, вам хорошо идти.
Ответ 4
вы должны 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
есть не что иное, как обертка script, которая делает именно это: удалите файл из индекса и добавьте его под другим именем
Ответ 5
Подумайте о своих файлах с точки зрения 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,
- нет iphone.css (он удаляется - git предупреждает об этом -).
- есть новый файл mobile.css.
- Эти файлы полностью не связаны.
Итак, git сообщает о уже знакомых файлах (iphone.css) и новых файлах, которые он обнаруживает ( mobile.css), но только тогда, когда файлы находятся в индексе или HEAD git начинает проверять их содержимое.
В настоящий момент ни "iphone.css deleteion", ни 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
- это опция "обнаружить переименования" для git diff
. -M
означает -M50%
(50% или более сходства сделают git выражать его как переименование), но вы можете уменьшить это до -M20%
(20%), если вы сильно отредактируете mobile.css.
Ответ 6
Git распознает файл из содержимого, вместо того, чтобы рассматривать его как новый невоспроизводимый файл
Что вы ошибетесь.
Только после того, как вы добавите файл, git распознает его из содержимого.
Ответ 7
Шаг1: переименуйте файл из старого файла в новый файл
git mv #oldfile #newfile
Шаг 2: git фиксация и добавление комментариев
git commit -m "rename oldfile to newfile"
Шаг 3: нажмите это изменение на удаленный сервер
git push origin #localbranch:#remotebranch
Ответ 8
Для git 1.7.x для меня работали следующие команды:
git mv css/iphone.css css/mobile.css
git commit -m 'Rename folder.'
Не нужно было добавлять git, поскольку исходный файл (т.е. css/mobile.css) уже был в ранее сохраненных файлах.
Ответ 9
Вы не выполнили результаты своего искателя. Я верю, что если вы сделали переход через Finder, а затем выполнили git add css/mobile.css ; git rm css/iphone.css
, git вычислил хэш нового файла и только потом поймет, что хеши файлов совпадают (и, следовательно, переименовываются).
Ответ 10
В случаях, когда вам действительно нужно переименовывать файлы вручную, например. используя script для пакетного переименования пучка файлов, то с помощью git add -A .
работал у меня.
Ответ 11
Для пользователей Xcode: если вы переименуете свой файл в Xcode, вы увидите, что значок значка изменится на добавление. Если вы выполняете фиксацию с использованием XCode, вы фактически создадите новый файл и потеряете историю.
Обходной путь прост, но вы должны сделать это, прежде чем совершать использование Xcode:
- Сделайте git статус в своей папке. Вы должны увидеть, что поэтапные изменения верны:
переименовано: Project/OldName.h → Project/NewName.h
переименован: Project/OldName.m → Project/NewName.m
- сделать commit -m 'изменить имя'
Затем вернитесь к XCode, и вы увидите, что значок изменен с A на M, и он сохраняет для фиксации изменений furtur при использовании xcode.