Подтвердить что ты не робот

Тайна отсутствующего коммита по слияниям

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

master----\----commit A----cherry-picked changesets from topic---commit B--\----commit C----merge---
           \                                                                \              /
            topic-----------------------------------------------------------merge---------/

Теперь моя проблема заключается в том, что когда master объединяется в ветвь topic (чтобы обновить ее с помощью коммитов A и B), набор изменений, введенный фиксацией B, просто не существует! Если commit B модифицировал файлы foo и bar, даже при большом количестве не отображаются те файлы, которые были изменены с помощью слияния. В файлах foo и bar

нет никаких конфликтов.

Теперь, когда я объединять topic обратно в master, commit B действует в обратном порядке без ЛЮБОГО журнала или трассировки разворота!

Что могло быть не так?

4b9b3361

Ответ 1

master----\----commit A----cherry-picked changesets from topic---commit B--\----commit C----merge---
           \                                                                \              /
            topic-----------------------------------------------------------merge---------/
                                                                            ~~~~~
                                                                              ^
                                                                              + here you merged B in topic

Существует слияние уже в теме, которая имеет фиксацию B как родителя. Таким образом, B полностью сливается в тему и больше не будет объединен.

Поскольку у вас нет изменений в теме, вы, по-видимому, вернули их по теме, либо в самом слиянии, либо в следующем коммите. Такое обращение является регулярной фиксацией для алгоритма слияния и не сливается с мастером. Поэтому, когда вы объединяете тему в master, эти изменения фиксации будут объединены, возвращая commit B.

Чтобы получить изменения с B назад, вы должны либо:

  • Найдите и верните отмену изменений B в теме.
  • Cherry-pick B (git cherry-pick B) по теме.
  • Повторите слияние, замените тему после слияния нового слияния и забудьте исходную ветвь, но поскольку это связано с перемоткой, вы можете сделать это только в том случае, если вы управляете всеми репозиториями, имеющими ветвь.

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

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

----\-- A -------- B' -- B2 --\
     \                         \
      D -- B -- E -----------merge

где B' выбирает B и B2 изменяет тот же код, что и B. В этом случае слияние будет видно, что одна сторона сделала B, а другая сторона сделала B2, потому что вишня-выбор скрыт B2 и таким образом объявит конфликт между B и B2. И если вы не будете внимательно смотреть на историю, вы можете легко решить эту ошибку. Вы можете избежать проблемы, если при выборе фиксации вы тщательно слейте целевую ветку в источник, подобный этому:

----\-- A --------\- B' -\- B2 --\
     \             \      \       \
      D -- B -- E --m1-----m2----merge

где m1 является нормальным слиянием без участия вишневого захвата, а m2 разрешается с локальной версией, потому что на удаленных видах только вишневые изменения. Это обеспечит бесперебойную работу последующих слияний.

На самом деле для этого можно написать стратегию слияния для Git.

Ответ 2

Не знаю, почему B не существует, но я бы рекомендовал перезагрузить topic поверх master вместо слияния master в topic.

Ваши собранные вишни коммиты дублируются в master, и это не очень хорошо работает при объединении master в ветку (topic) с теми же самыми коммитами, которые уже присутствуют. Это отличается, если вы переформатируете topic поверх master: любая дублируемая фиксация не воспроизводится.

Конечно, проблема с rebase заключается в том, что это изменения topic SHA1, что является проблематичным, если вы уже нажали topic на восходящее репо (и другие люди уже вытащили topic).

В общем, как показано в "Каков правильный рабочий процесс git с разделяемыми ветвями функций?", вы бы хотели избежать "back-merge" ( master до topic), и использование в основном объединяется только одним способом (topic to master).