почему git rebase помечает конфликты в новых файлах, относящихся к ветке - PullRequest
2 голосов
/ 17 июня 2019

У меня сейчас есть сводящая с ума маленькая проблема с git rebase.

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

Что я сделал

Я клонировал удаленный репозиторий и обновлял его с помощью git pull --rebase, а затем перебазировал этот локальный мастер в локальную ветку:

    git pull --rebase (on master)
    git checkout mybranch
    git rebase master mybranch
    <rebases cleanly>

, который выглядит примерно так:

    master ----o-o-o-o--------o-o-------------o
                \          \ (pull --rebase)   \(pull --rebase (successful)
    local master ---o-o      o-o-o-o            rebase master to mybranch fails 
                       \            \ (rebase)    
    mybranch           --------A-B   o-A-B-C       

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

    git pull --rebase (on master branch and successfully)
    git checkout mybranch
    git rebase master mybranch (conflicts in files that do not exist on master)

Я никогда не сливал ничего с локальным или удаленным.

В основном, я добавил 4 файла из 100, которые постоянно вызывают конфликты, и во время ребазинга они хотят снова и снова объединяться с одним и тем же различием снова и снова.

git version 2.9.3

Вещи, которые я пробовал (это не помогло или не помогло)

  1. Подтвердил, что я никогда ничего не фиксировал в локальной ветке master и что эти файлы конфликтов не существуют
  2. клонировал еще одну копию репозитория и подтвердил, что я никогда ничего не совершал, и что эти файлы конфликтов не существуют
  3. Я сделал "git reset --hard HEAD" перед ребазингом, без помощи. удалены некоторые локальные файлы .gitignore, которые не отслеживались, чтобы попытаться изолировать любое поведение, которое может происходить и не согласовываться между ветвями.
  4. Я пытался разрешить эти конфликты с помощью mergetool

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

  5. Я попробовал Git rebase --skip но это не показалось полезным для вышеизложенного, поэтому я прервал
  6. Я попытался объединиться, но через час сдался. Есть сотни коммитов, которые я сделал локально.
  7. Я включил rerere.enabled и попробовал снова. rebase пытается применить "recorded preimage", но не удается, и меня просят объединить не конфликты вручную, как раньше.

Вещи, которые работали

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

другая информация

Я слил свою ветку обратно в мастер, и теперь я обнаружил, что выполнение git pull --rebase для мастера теперь имеет

    git checkout mybranch
    git merge master mybranch (success)
    git checkout master
    git merge mybranch master (success)
    git pull --rebase (conflicts in files that dont exist on remote.)

выглядит примерно так:

    master ----o-o-o-o--------o-o-------------o-------------------------------------------------------
                \          \ (pull --rebase)   \(pull --rebase (clean)           merged back (clean)  \ rebase
    local master ---o-o      o-o-o-o            o------------------------------o-----------------------X (rebase unclean)
                       \            \ (rebase)   \ merge to mybranch (clean)  /
    mybranch           --------A-B   o-A-B-C      o-----A-B-C-o-...-o-------
                                         (clean, before it stopped working)

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

1 Ответ

0 голосов
/ 17 июня 2019

Исходя из вашего комментария "[...] первые ~ 20 коммитов в интерактивном повторе повтора [...]", я полагаю, что могу объяснить проблему.

Предположим, что коммиты перечислены так:

A
B
C
A
B
C

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

  1. Применить фиксацию A - Нет проблем
  2. Применить фиксацию B - Нет проблем
  3. Применить фиксацию C - Нет проблем
  4. Apply commit A - CONFLICT, потому что эти изменения уже применены

Конечно, когда вы вручную решаете конфликт, ничего не появляется, потому что изменения идентичны. Именно поэтому merge работает без проблем - он сравнивает только последние версии.


Итак, как это исправить?

  1. git rebase -i master
  2. Удалить дубликаты коммитов. Это утомительно, но понадобится только один раз
  3. git push -f

Но как это случилось?

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

master o-o-o-o-o
            \
branch-1     o-A-B-o
                    \
branch-2             o-o

Затем branch-1 был обновлен с помощью git rebase master:

master o-o-o-o-o
            \   \
branch-1     \   o-A`-B`-o
              \
branch-2       o-A-B-o-o

Затем branch-2 было обновлено с помощью git rebase branch-1:

master o-o-o-o-o
                \
branch-1         o-A`-B`-o
                          \
branch-2                   o-A-B-o-o

И, таким образом, коммиты дублируются.


Что дальше?

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

Если дублированные сообщения коммита поступили от mybranch, то я предполагаю, что в какой-то момент у вас была дочерняя ветка и вы допустили ошибку при получении последних изменений от мастера. Я использую процесс, описанный в этой статье , чтобы справиться с этой ситуацией (короче, вам нужно использовать флаг --onto при отбрасывании branch-2).

...