Обработка переименований файлов в 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?

604   11  

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.css

git говорит вам точно, что произошло: (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:

  1. сделайте статус git в своей папке. Вы должны увидеть, что поэтапные изменения являются правильными:

переименовано: Project / OldName.h - > проект / Новое имя.ч переименованы: проект/Старое_имя.м - >Проект / Новое Имя.м

  1. do commit-m 'name change'

затем вернитесь к XCode, и вы увидите, что значок изменился с A на M, и теперь он сохраняется для фиксации изменений furtur при использовании xcode.

Comments

    Ничего не найдено.