Почему ошибка переключения веток после сдавливания?Нечего совершать - PullRequest
0 голосов
/ 03 января 2019

Я просто раздавил свои удаленные коммиты, а затем принудительно подтолкнул их к удаленному.A git status не показывает изменений.Почему тогда я получаю эту ошибку при попытке извлечь ветку разработки?

ошибка: Ваши локальные изменения в следующих файлах будут перезаписаны извлечением:
[файл здесь]
Пожалуйстапередайте изменения или спрячьте их перед тем, как переключать ветви.
Прерывание

Вот что было сделано:

git rebase -i origin/feature/EX-1576~14 feature/EX-1576
git push --force origin feature/EX-1576

И git status ничего не показывает:

$ git status
On branch feature/EX-1576
Your branch is up to date with 'origin/feature/EX-1576'.

nothing to commit, working tree clean

Насколько я понимаю, ошибка возникает, когда у вас есть локальные изменения, но у меня нет локальных изменений.Я просто хочу сделать это:

git checkout develop

1 Ответ

0 голосов
/ 03 января 2019

TL; DR

Следуйте советам Git: для каждого файла, который он назвал, переместите этот файл куда-нибудь (из пути, возможно, из проекта целиком) или передайте его. Затем выполните проверку и посмотрите, какие файлы были заменены этими файлами, и решите, сохранять ли замены или использовать сохраненные копии, сделанные вами до проверки.

Будьте осторожны с git update-index --assume-unchanged или git update-index --skip-worktree: в некоторых случаях они хорошо работают, но настраивают вас именно на эту ловушку.

Поскольку вы работаете в Windows, по умолчанию файлы из файлов (например,) readme сопоставляются с другими файлами README - Windows не может хранить оба файла; он просто забивает один из них - будьте осторожны с именами файлов, чувствительными к регистру, которые обычно делают некоторые программисты Linux. : -)

Long

Насколько я понимаю, ошибка возникает при локальных изменениях ...

Это не совсем верно. Вы получаете эту ошибку, когда операция - в данном случае git checkout - перезаписывает некоторое состояние .

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

Разница между состоянием и изменениями подобна разговору о погоде: говорить, что сегодня теплее, чем вчера, говорит о температуре, что-то одно, но не все. Сказать, что вчера было 15 ° C (59 ° F), а сегодня 20/68, говорит вам все о температуре. (Ну, во всяком случае, об этой одной температуре.) Обратите внимание, что потребовалось два состояния , чтобы придумать изменение : мы должны вычесть вчерашнюю температуру из сегодняшней, чтобы увидеть, насколько теплее или холоднее это может быть.

В любом случае, фиксирует состояние хранилища: полная, полная копия каждого файла, который был зафиксирован, на момент его фиксации. Эта копия на самом деле взята из Git index , но мы пока проигнорируем это тонкое различие. Это собирается неожиданно появиться через мгновение, все же. Таким образом, каждый коммит очень независим от любого другого коммита.

Ваше рабочее дерево , с другой стороны, не является чем-то, что Git сохраняет (вообще-то, на самом деле, из-за индекса). Вы используете его для работы с вашими файлами, потому что зафиксированные копии находятся в специальном, замороженном, сжатом (иногда очень сжатом) формате Git-only. Чтобы сделать их полезными, Git необходимо развернуть их в файлы обычного формата, которые вы можете использовать, и изменить , если хотите. Эти расширенные копии помещаются в ваше рабочее дерево.

Теперь, что касается рабочего дерева, так это то, что ему разрешено содержать файлы, которые вы не будете фиксировать. Это то, что Git называет неотслеживаемыми файлами. Обычно, если в вашем рабочем дереве есть файл, который не отслежен - который не будет зафиксирован - Git будет жаловаться на этот файл. Вы можете заставить Git замолчать, перечислив неотслеживаемый файл в .gitignore, но это сложнее, чем кажется. Вот где Git снова ударил вас по лицу существованием индекса.

Указатель - странная и замечательная, но и противная вещь, которая в значительной степени уникальна для Git. Между коммитами, которые хранят файлы в замороженной сжатой форме только для Git, и рабочим деревом, которое позволяет вам работать с вашими файлами, Git помещает третью копию каждого файла. Индексная копия каждого файла находится в специальном формате Git-only, но вместо того, чтобы быть замороженным, это просто готов , чтобы заморозить: немного грязно, если хотите. Дело в том, что вы можете изменить эту копию, и вот что делает git add: она копирует файл из рабочего дерева в индекс.

Это на самом делеТолько наличие индексной копии, которая определяет, отслеживается ли файл.Если файл находится в индексе, он отслеживается;если нет, это не отслеживается.Перечисление файла в .gitignore означает: , если его нет в индексе и в рабочем дереве, не жалуйтесь. Но у него есть второй побочный эффект: он дает разрешение Git уничтожить файл, в некоторых случаях.

Проблемы с именем файла

Программисты Linux с радостью пишут и фиксируют два разных файла, один с именем README и другой с именем readme или Readme.Или они делают то же самое с заголовочными файлами: ip.h и IP.h (в старых деревьях ядра Linux).Когда кто-то, использующий Mac или Windows, пытается работать с этими коммитами, его укушает тот факт, что рабочее дерево в этих системах не может поместить оба файла на место.(Индекс Git прекрасно с этим справляется, потому что индекс на самом деле является файлом, .git/index.)

Если вы переключаетесь с коммита с файлом с именем README на файл с Readme,или это имеет и то и другое, Git иногда будет немного смущен этим и не будет знать, что делать.(Когда-нибудь Git должен быть умнее.)

предположим, что без изменений, и skip-worktree

В любом случае, предположим, что файл имеет в индексе.Если вы измените копию рабочего дерева, Git сообщит вам, что у вас есть измененный отслеживаемый файл.Если вы не хотите, чтобы Git постоянно напоминал вам об этом, вы можете использовать git update-index --assume-unchanged или git update-index --skip-worktree для особой пометки этого файла.

Когда вы делаете это - и я думаю, что вы, вероятно, сделали - Git прекращает сравнение индексной копии файла с копией рабочего дерева для команд git status и не копирует копию рабочего дерева файла поверх индексной копии для команд git add,Это означает, что вы можете взять файл конфигурации, изменить его по какой-то причине, и в то же время иметь новые коммиты - которые используют index копию файла - хранить оригинал версия файла, та, которая вышла из коммита и вошла в ваше рабочее дерево до того, как вы установили бит предположения без изменений или пропуска рабочего дерева.

Но git checkout должен, когда он идетчтобы переключиться на другой коммит, замените индексную копию этого файла на (другую) зафиксированную копию в коммите, на который вы собираетесь переключиться.Когда это происходит, Git не только обновляет копию индекса, но и перезаписывает копию рабочего дерева.Поэтому, если у вас есть файл, помеченный одним из этих двух битов, вы можете получить эту ошибку, когда используете git checkout.

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

Существуют также угловые случаи с наполовину проигнорированными файлами

Предположим, с другой стороны, вы не установили эти индексные биты с помощью git update-index.Вы могли бы по-прежнему иметь обычный, неотслеживаемый файл, возможно, даже тот, который указан в .gitignore, чтобы Git молчал об этом.Но некоторые другие коммиты могут иметь (другую версию) тот же файл, и если у вас есть Git переключиться на , что коммит, Git придется заменить вашнеотслеживаемый файл рабочего дерева с версией из коммита, в которой он является отслеживаемым файлом.

В этом случае git checkout иногда будет, но не всегда, также жаловаться.Обычно это говорит о том, что извлечение будет перезаписывать неотслеживаемый файл.Если файл указан в .gitignore, это даст некоторым частям Git разрешение на его заделку.К счастью, git checkout обычно очень осторожен с этими вещами.

...