Попытка git merge прекращает работу без ошибок - PullRequest
0 голосов
/ 18 декабря 2018
C:\Users\danie01\fox (fox-45481 -> origin)
λ git merge feature/master-stg
error: The following untracked working tree files would be overwritten by merge:
        blah/blah/blahblah.cpp
        ... (many files)
        common/wizard/wizpa
Aborting

C:\Users\danie01\fox (fox-45481 -> origin)
λ

Прошло очень много времени с тех пор, как я ранее слился.Кроме того, последний коммит в этой ветке был слиянием.

Интересно, что конечный файл в этом списке обрезается (у него нет расширения файла или даже полное имя файла) - это может бытьпроблема с моим буфером?

Я только что проверил это из удаленной ветки;У меня нет разрешения на слияние с удаленной веткой, и мне нужно создать запрос на слияние.Может ли быть так, что git пытается слиться непосредственно с удаленной веткой?

Что здесь можно сделать?Я в растерянности.

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

Может ли случиться так, что git пытается объединиться непосредственно с удаленной веткой?

Нет.Это не то, как Git выполняет слияния.

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

Интересно, что окончательный файл в этом списке обрезан (у него нет расширения файла или даже полного имени файла) - может ли это быть проблемой с моим буфером?

Я не уверен, что вы подразумеваете под этим, но, конечно, имена файлов в выводе не должны быть усечены.

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

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

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

Между этими двумя вещами этоЛегко для вас неотслеживаемых файлов .Не отслеживаемый файл - это просто файл, который существует в вашем рабочем дереве прямо сейчас, но сейчас его нет в вашем индексе.Каждый такой файл можно либо игнорировать, либо не игнорировать, но в любом случае он не отслеживается.Если он не проигнорирован, git status будет жаловаться на это.

Перед тем, как приступить к слиянию, рекомендуется убедиться в двух вещах: во-первых, что вы еще этого не сделалив середине какой-то другой операции, и во-вторых, что ваши HEAD commit, index и work-tree все совпадают с точки зрения всех ваших отслеживаемых файлов.Команда git merge делает большую часть этого автоматически, но сначала неплохо запустить git status и убедиться, что в нем написано nothing to commit, working tree clean.

Это нормально, если вы также жалуетесь на различные файлы без отслеживания, так каку нас есть шанс разобраться с ними в одно мгновение.Теперь, когда вы уверены, что нет выполняемой работы, которая может быть потеряна, вы вводите команду слияния:

λ git merge feature/master-stg

Теперь Git выполняет следующие действия:

  • Поискидентификатор хэша текущего коммита (git rev-parse HEAD).
  • Найдите идентификатор хэша указанного коммита (git rev-parse feature/master-stg).
  • Используйте git merge-base --all, чтобы найти базу слияния (s) из этих двух коммитов.База слияния - это коммит, а иногда и более одного коммита, который находится на обеих ветвях и является лучшим таким коммитом.

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

git merge-base --all HEAD feature/master-stg

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

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


1 Файлы внутри коммита определенно заморожены, но они существуют в этой форме , потому что коммит существует.Если вам удастся заставить Git забыть об этом коммите, сам коммит со временем исчезнет.Это очень трудно сделать, поэтому коммиты в основном постоянны.Они полностью только для чтения, однако: ничто в любом коммите, определенном его хэш-идентификатором, не может измениться.

2 Технически, вы можете удалитькопия рабочего дерева, оставляя индексную копию на месте.Я думаю, это все еще будет «отслеживаемый файл», хотя номенклатура становится немного шаткой.(Как можно отследить файл, если этот файл не существует?)


Как Git выполняет реальное слияние

Теперь, когда Git знает три входа до слияния - базовый коммит, --ours или HEAD коммит и другой или --theirs коммит, из feature/master-stg, Git, по сути, будет запускать две git diff команды:

git diff --find-renames <hash-of-base> HEAD                # what we changed
git diff --find-renames <hash-of-base> feature/master-stg  # what they changed

Работа слияния теперь довольно проста и довольно очевидна.Вот что он должен будет сделать:

  • Начать со всех файлов, которые были в базовом коммите слияния.
  • Затем, если мы изменили или создалиили удалили (и / или переименовали) файл, и они не коснулись файла, используйте наше изменение.
  • Если они изменили или создали или удалили (и / или переименовали) файл, и мы не коснулись файла, используйте их изменение.
  • Если мы и они обаизменил или создал или удалил (и / или переименовал) тот же файл , объединяем эти два отдельных набора изменений.

В простых случаях выполняем всеиз этого довольно просто.Например, возможно, мы оба касались README.md, но по-разному;мы изменили a/main.py, а они не изменились;и они изменились b/prog.cc, а мы нет.Таким образом, результатом слияния будут все базовые файлы, кроме README.md, который имеет объединенные изменения, наших a/main.py и их b/prog.cc.

Если все пойдет хорошо, Gitфиксирует полученные файлы, попутно помещая их в свой индекс и рабочее дерево.Новый коммит обновляет текущую ветку, так что, независимо от того, какая ветвь HEAD name, теперь присваивается имя новой фиксацииПервый родитель нового коммита - это предыдущий наконечник текущей ветви, а второй родитель нового коммита - другой коммит (в этом случае все еще идентифицируемый feature/master-stg).Так как у нового коммита есть два родителя, это коммит слияния .

В сложных случаях что-то идет не так, и слияние либо останавливается в середине - что является самым грязным случаем - илиникогда не начинаетсяУ вас есть последний случай: слияние никогда не начинается.

У вас есть неотслеживаемые файлы, которые они имеют в своем коммите

Что здесь не так, так это то, что в их коммите -один с именем feature/master-stg - у них есть зафиксированные файлы, которые:

  • не находятся в базовом коммите слияния, а
  • нет в вашем HEADcommit any.

Git распечатал полный список этих файлов:

blah/blah/blahblah.cpp
... (many files)
common/wizard/wizpa

В выводе git diff --find-renames <hash of merge base> feature/master-sta, они добавили эти файлы .Вы можете подтвердить это, запустив тот же git diff самостоятельно, возможно, с --name-status, чтобы он был короче и более читабельным.

У вас нет этих файлов в вашем HEAD коммите, но вы do прямо сейчас хранят эти самые файлы в вашем рабочем дереве .

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

Решение состоит в том, чтобы сделать то, что сказал или должен был сказать Git (возможно, он потерян в части "blahblahblah"):

Plпросто переместите или удалите их перед слиянием.

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

0 голосов
/ 18 декабря 2018

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

...