Git Checkout ошибки, хотя Git сообщает о состоянии, что рабочее дерево чистое - PullRequest
0 голосов
/ 08 ноября 2018

Я в своем местном my-feature филиале

git status отчеты nothing to commit, working tree clean

Я хочу переключиться на разработку ветки и сделать там git fetch и git merge (я предпочитаю это git pull)

Однако, это приводит к ошибке ниже

Здесь я сначала проверяю статус, и он показывает, что все чисто

mymbp:MyProj username$ git status
On branch my-feature
nothing to commit, working tree clean

Далее я пытаюсь оформить свою ветку разработки, которая является существующей локальной веткой

On branch my-feature
nothing to commit, working tree clean
mymbp:MyProj username$ git checkout develop
error: Your local changes to the following files would be overwritten by checkout:
    MyProj.sln
Please commit your changes or stash them before you switch branches.
Aborting

Он жалуется, что myProj.sln был изменен, хотя git status говорит, что ничего не изменилось.

Выпуск git status снова подтверждает, что ничего не изменилось

mymbp:MyProj username$ git status
On branch my-feature
nothing to commit, working tree clean

ОБНОВЛЕНИЕ 1

Doing git ls-files --stage --debug MyProj.sln показывает, как показано ниже, и я не вижу 4000 или 8000 (--skip-worktree или --assume-unchanged flags):

mymbp:MyProj username$ git ls-files --stage --debug MyProj.sln
100644 40c3593ed572beb2139c189455274f8900a1340c 0   MyProj.sln
  ctime: 1541703970:521058155
  mtime: 1541637062:121492660
  dev: 16777220 ino: 8470003
  uid: 501  gid: 20
  size: 55684   flags: 0
mymbp:MyProj username$ 

Issuing git show develop:MyProj.sln показывает мне количество файлов проекта и их GUID в решении, глобальные разделы для решения до и после решения, но вывод очень длинный, показывая только релиз, конфигурации отладки и некоторые GUIDS. Пока не знаю, что с этим делать.

ОБНОВЛЕНИЕ 2

Таким образом, он выглядит так, как будто файл MyProj.sln находится в рабочем дереве, но не в индексах и фиксации (HEAD). Исходя из объяснения @torek, выдача git add MyProj.sln должна добавить этот файл в индекс, но это не так, поскольку ничего не добавлено и состояние git ничего не возвращает до того, как я сделал git add и после того, как я это сделал. Тем временем git checkout по-прежнему жалуется, что MyProj.sln изменился. git diff также ничего не возвращает

ОБНОВЛЕНИЕ 3

Я также нашел кого-то, предложившего ввести эти 2 команды, чтобы получить хеш коммита HEAD и посмотреть, что в нем изменилось. Я вижу много файлов, дублирующих, а некоторые нет. Те, которые не являются файлами, которые я добавил в мою текущую ветку. Дублирующиеся файлы выглядят как удаленные

mymbp:MyProj username$ git rev-parse HEAD
1ca8d8a7c5eff0f2a03eb185f1b25aff27c1d2fd
mymbp:MyProj username$ git ls-tree -r 1ca8d8a7c5eff0f2a03eb185f1b25aff27c1d2fd

А вот и вывод

enter image description here

ОБНОВЛЕНИЕ 4

Моя конфигурация:

mymbp:MyProj username$ git config --list
credential.helper=osxkeychain
core.excludesfile=/Users/username/.gitignore_global
core.autocrlf=input
difftool.sourcetree.cmd=opendiff "$LOCAL" "$REMOTE"
difftool.sourcetree.path=
mergetool.sourcetree.cmd=/Applications/Sourcetree.app/Contents/Resources/opendiff-w.sh "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$MERGED"
mergetool.sourcetree.trustexitcode=true
user.name=User Name
user.email=username@somesystems.com
color.ui=true
color.status.changed=blue normal
color.status.untracked=red normal
color.status.added=magenta normal
color.status.updated=green normal
color.status.branch=yellow normal bold
color.status.header=white normal bold
commit.template=/Users/username/.stCommitMsg
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
remote.origin.url=https://github.com/SomeSystems/MyProj.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.develop.remote=origin
branch.develop.merge=refs/heads/develop
branch.feat-1.remote=origin
branch.feat-1.merge=refs/heads/feat/feat-1
branch.1234-refactoring.remote=origin
branch.1234-refactoring.merge=refs/heads/1234-refactoring
mymbp:MyProj username$ 

1 Ответ

0 голосов
/ 08 ноября 2018

Редактировать по обновлениям: здесь определенно что-то странное, хотя трудно точно сказать, что именно (захваченный вывод - изображения, поэтому невозможно проверить, к примеру, странные проблемы с Unicode). Ни один файл никогда не должен указываться дважды в выводе git ls-tree -r дерева коммитов. Я никогда не видел такого поведения от Git. есть проблемы с прописными и строчными буквами, особенно в Windows и MacOS, которые могут вызывать такое поведение, но это не соответствует тому, что вы здесь показываете.

Оригинальный ответ ниже

Сначала короткое примечание: в ваших тегах упоминается MacOS. В файловых системах MacOS по умолчанию регистр не учитывается, поэтому, если у вас есть файл с именем README.TXT и вы просите систему просмотреть файл с именем readme.txt, он покажет вам README.TXT. Если вы попросите систему добавить новый файл с именем readme.txt, вместо этого перезапишет существующий README.TXT и сохранит имя в верхнем регистре. Так что следите за файлами, имена которых отличаются только в том случае, если в коммите Git может быть файл myproj.sln, который перезапишет ваш файл MyProj.sln.


Существует как минимум две возможности, но давайте сначала рассмотрим наиболее вероятную:

  • Это означает, что существует файл, которого нет в текущем индексе и коммите, но равен в текущем рабочем дереве и называется MyProj.sln. Этот же файл является в коммите, который вы задали Git для git checkout. Так что Git перезапишет файл рабочего дерева, если вы успешно выполните git checkout этого другого коммита. Git предупреждает вас, что вы потеряете текущее содержимое этого файла.

  • Или существует файл, который равен в текущем индексе и рабочем дереве, с именем MyProj.sln. Копия рабочего дерева не совпадает с индексной копией. Обычно, git status сообщит вам, что файл изменен, но вы установили один из двух битов указателя, которые сообщают Git: не ищет изменения в файле и / или не сообщает Что касается изменений, если вы случайно их обнаружите, просто сохраните копию индекса так, как она есть. Эти два бита флага --assume-unchanged и --skip-worktree.

В обоих случаях, если вы успешно проверите коммит, который вы просите Git, он перезапишет копию рабочего дерева MyProj.sln. Если все в порядке, просто продолжайте и удалите файл сейчас, и git checkout продолжится.


Чтобы понять, в чем дело:

git ls-files --stage --debug MyProj.sln

Если вы не получите никакого вывода, файл отсутствует в индексе (и, следовательно, также отсутствует в текущем коммите, на основе вывода git status или отсутствия вывода). Это, в свою очередь, означает, что на данный момент это просто неотслеживаемый файл рабочего дерева.

Если вы получите вывод, он должен быть похож на этот вывод, который я получил здесь для другого файла:

$ git ls-files --stage --debug Makefile
100644 b08d5ea258c69a78745dfa73fe698c11d021858a 0       Makefile
  ctime: <number>:<number>
  mtime: <number>:<number>
  dev: <number>  ino: <number>
  uid: <number>  gid: <number>
  size: <number> flags: <number>

flags: <number> показывает биты предполагаемого неизменного и дерева пропусков, хотя и не в удобном для человека формате: пропустить дерево работ 4000, а другое 8000 (если оба будут установлены, вы получите c000). Установив бит skip-worktree, я на самом деле получаю:

size: 96311   flags: 40004000

при установке бита без изменений дает мне:

size: 96311   flags: 8000

В коммите, на который вы хотите переключиться (подсказка develop), есть зафиксированная версия файла, которую вы можете увидеть (без перезаписи текущей копии) с помощью:

git show develop:MyProj.sln

Обратите внимание, что как только вы git checkout develop, этот файл будет во всех трех активных местах: текущая фиксация, индекс и рабочее дерево. Если для коммита подсказки my-feature файл не имеет файл, переключение обратно с develop на my-feature приведет к удалению файла из рабочего дерева. Способ запомнить большинство из этого:

  • Коммиты сделаны из индекса.
  • Поэтому коммиты извлекаются в сначала в индекс (а затем в дерево работ).
  • Индекс отслеживает то, что в рабочем дереве должно быть зафиксировано. Индексная копия - это та, которая входит в коммит. git status сравнивает индекс с рабочим деревом, чтобы сказать вам, что вы должны скопировать в индекс.
  • При переключении коммитов файлы рабочего дерева, которые не являются в индексе, но должны основываться на новом коммите, получают созданный; файлы, которые являются в индексе, но нужно , а не быть там, основываясь на новом коммите, получить удалено .
  • Файлы в рабочем дереве, которые не в индексе, не отслеживаются и остаются одни.

После этого момента биты предположения без изменений и пропуска рабочего дерева, если вы их установили, являются лишь незначительными изменениями в большинстве случаев самосогласованных правил. Правила .gitignore также начинают иметь смысл: файл, указанный в .gitignore, - это файл, который git status не будет жаловаться на то, что он не отслежен. (Однако, важный побочный эффект, который .gitignore делает Git свободным для clobber таких неотслеживаемых файлов в некоторых случаях, сложнее запомнить или объяснить в этом отношении.)

...