Обработка переименований файлов в git
Я читал, что когда переименование файлов в git, вы должны зафиксировать любые изменения, выполнить переименование, а затем поместить переименованный файл. Git распознает файл из содержимого, а не видит его как новый неотслеженный файл и сохраняет историю изменений.
однако, делая именно это сегодня вечером я в конечном итоге вернулся к git mv.
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
переименовать свой стиль с помощью 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
#
похоже, у нас все хорошо. Так почему же git не распознал переименование в первый раз, когда я использовал Finder?
11 ответов:
на
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что приводит к тому, что вы ожидайтеTanascius@H181 /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вероятно, нет.
вы должны добавить два измененных файла в индекс, прежде чем git распознает его как движение.
единственная разница между
mv old newиgit mv old newэто то, что git mv также добавляет файлы в индекс.
mv old newзатемgit add -Aтоже бы сработало.обратите внимание, что вы не можете просто использовать
git add .потому что это не добавляет удаления в индекс.посмотреть разница между "git add-A" и "git add ."
лучше всего попробовать его для себя.
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 status и git commit --dry-run-a показывает два разных результата, где git status показывает bbb.txt как новый файл/ aaa.txt удаляется, и команды --dry-run показывают фактическое переименование.
~/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". Если он показывает, что файл переименован, вы хорошо идти.
вы должны
git add css/mobile.cssновый файл иgit rm css/iphone.css, Так что мерзавец знает об этом. тогда он покажет тот же результат в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это не более чем сценарий, который делает именно это: удалить файл из индекса и добавить его под другим именем
давайте подумаем о ваших файлах с точки зрения 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 (удаляется -ГИТ предупреждает об этом-).
- есть новый файл мобильная.css.
- эти файлы совершенно не связаны.
Итак, git советует о файлах, которые он уже знает (iphone.css) и новые файлы, которые он обнаруживает (мобильная.css) но только когда файлы находятся в индексе или головном git начинает проверять их содержимое.
на данный момент, ни "iphone.удаление УСБ", ни мобильная.css на индекс.
добавить iphone.удаление css для индексирования
$ git rm iphone.cssgit говорит вам точно, что произошло: (iphone.css удалены. Больше ничего не произошло)
затем добавить новый файл мобильная.css
$ git add mobile.cssна этот раз как удаление, так и новый файл находятся в индексе. Теперь git обнаруживает, что контекст одинаковый и предоставляет его как переименование. На самом деле, если файлы на 50% похожи, он обнаружит это как переименование, которое позволит вам изменить мобильная.css немного, сохраняя операцию в качестве переименования.
смотрите, это воспроизводимо на
git diff. Теперь, когда ваши файлы находятся в индексе, вы должны использовать--cached. Редактировать мобильная.css немного, добавьте это в индекс и посмотрите разницу между:$ git diff --cachedи
$ git diff --cached -M
-Mэто опция "обнаружить переименования" дляgit diff.-Mрасшифровывается как-M50%(50% или более сходство заставит git выразить его как переименование), но вы можно уменьшить до-M20%(20%), если вы редактируете мобильный.css много.
Git распознает файл из содержимого, а не видит его как новый неотслеженный файл
вот где вы ошиблись.
только после вы добавляете файл, который git распознает его из содержимого.
Шаг 1: переименуйте файл из oldfile в newfile
git mv #oldfile #newfileШаг 2: git commit и добавить комментарии
git commit -m "rename oldfile to newfile"Шаг 3: Нажмите это изменение на удаленный север
git push origin #localbranch:#remotebranch
для git 1.7.x для меня работали следующие команды:
git mv css/iphone.css css/mobile.css git commit -m 'Rename folder.'не было необходимости в git add, так как исходный файл (т. е. css/mobile.css) уже был в зафиксированных файлах ранее.
вы не ставили результаты вашего движения finder. Я считаю, что если вы сделали ход через Finder, а затем сделали
git add css/mobile.css ; git rm css/iphone.css, git вычислит хэш нового файла и только тогда поймет, что хэши файлов совпадают (и, следовательно, это переименование).
в случаях, когда вам действительно нужно переименовать файлы вручную, например. использование скрипта для пакетного переименования группы файлов, а затем с помощью
git add -A .работал для меня.
для пользователей Xcode: если вы переименуете свой файл в Xcode, вы увидите, что значок значка изменится на добавление. Если вы сделаете фиксацию с помощью XCode, вы фактически создадите новый файл и потеряете историю.
обходной путь прост, но вы должны сделать это перед фиксацией с помощью Xcode:
- сделайте статус git в своей папке. Вы должны увидеть, что поэтапные изменения являются правильными:
переименовано: Project / OldName.h - > проект / Новое имя.ч переименованы: проект/Старое_имя.м - >Проект / Новое Имя.м
- do commit-m 'name change'
затем вернитесь к XCode, и вы увидите, что значок изменился с A на M, и теперь он сохраняется для фиксации изменений furtur при использовании xcode.
Comments