Git: "более старая" версия перетирает "более новую" при мердже — почему?
От: Dair Россия https://dair.spb.ru
Дата: 21.01.14 13:42
Оценка:
Коллеги,

Иногда в мерджах появляются ошибки.

Пример такой:

Есть в репозитории File1.cpp и File2.cpp.
1. Разработчик-1 делает брэнч, правит (по логам проверил) только File1.cpp.
2. Разработчик-2 после делает брэнч, правит только File2.cpp
3. Потом разработчик-2 мерджит свои изменения с основной веткой.
4. Потом разработчик-1 мерджит свои изменения с основной веткой.

Логично ожидается, что в результате появятся изменения от обоих разработчиков.
Но почему-то после шага 4 File2.cpp меняется на тот, который был на этапе 1.

Конфликтов git не выдавал, поэтому разработчик-1 ничего не заподозрил.

Куда копать? Почему такое вообще могло произойти?
git
Re: Git: "более старая" версия перетирает "более новую" при мердже — почему?
От: Dziman США http://github.com/Dziman
Дата: 21.01.14 14:07
Оценка:
Здравствуйте, Dair, Вы писали:

D> Коллеги,


D> Иногда в мерджах появляются ошибки.


D> Пример такой:


D> Есть в репозитории File1.cpp и File2.cpp.

D> 1. Разработчик-1 делает брэнч, правит (по логам проверил) только File1.cpp.
D> 2. Разработчик-2 после делает брэнч, правит только File2.cpp
D> 3. Потом разработчик-2 мерджит свои изменения с основной веткой.
D> 4. Потом разработчик-1 мерджит свои изменения с основной веткой.

D> Логично ожидается, что в результате появятся изменения от обоих разработчиков.

D> Но почему-то после шага 4 File2.cpp меняется на тот, который был на этапе 1.

D> Конфликтов git не выдавал, поэтому разработчик-1 ничего не заподозрил.


D> Куда копать? Почему такое вообще могло произойти?


Я из самого реального вижу только что не бранч с изменениями вмержили в основную ветку, а основную ветку вмержили в бранч с изменениями.

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

P.S. Какая версия git? ОС у разработчиков? File1 и File2 случаем не идентичный файл но с разными путями?
avalon 1.0rc3 build 430, zlib 1.2.5
Re[2]: Git: "более старая" версия перетирает "более новую" при мердже — почему?
От: Dair Россия https://dair.spb.ru
Дата: 21.01.14 14:29
Оценка:
D>> Конфликтов git не выдавал, поэтому разработчик-1 ничего не заподозрил.

D>Я из самого реального вижу только что не бранч с изменениями вмержили в основную ветку, а основную ветку вмержили в бранч с изменениями.

О. Да нет, по истории всё ровно.

D>А вообще я бы попробовал воспроизвести проблему: родительский коммит известен, изменения известны: делаем ветки, изменяем, мержим на одном компе и смотрим что на выходе.


Да, ща попробую, спасибо.

D>P.S. Какая версия git?

D>ОС у разработчиков? File1 и File2 случаем не идентичный файл но с разными путями?

1.8.4.3 на сервере.

У разработчика-1 Windows, git 1.8.4-preview20130916
У разработчика-2 Linux, git 1.8.1.2

File1 и File2 совешенно разные, в разных путях и называются по-разному, один .cpp, другой .java.
Re[2]: Git: "более старая" версия перетирает "более новую" при мердже — почему?
От: dilmah США  
Дата: 21.01.14 17:04
Оценка:
D>Я из самого реального вижу только что не бранч с изменениями вмержили в основную ветку, а основную ветку вмержили в бранч с изменениями.

а чем это неправильно?

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

Никогда никаких проблем не было.
AFAIK направление мержа вообще не влияет на результат.
Re[3]: Git: "более старая" версия перетирает "более новую" при мердже — почему?
От: Dziman США http://github.com/Dziman
Дата: 21.01.14 17:20
Оценка:
Здравствуйте, dilmah, Вы писали:

d> D>Я из самого реального вижу только что не бранч с изменениями вмержили в основную ветку, а основную ветку вмержили в бранч с изменениями.


d> а чем это неправильно?


d> Я так всегда делаю:

d> создается бранч для некой фичи, далее на протяжении разработки (которая может вестись с перерывами месяцы) mainline регулярно мержится в бранч с изменениями,
d> потом в конце, перед окончательным пушем, бранч с изменениями мержится в mainline.
Так я и имею в виду что вот это пункт как бы пропущен.
avalon 1.0rc3 build 430, zlib 1.2.5
Re[3]: Git: "более старая" версия перетирает "более новую" при мердже — почему?
От: Dziman США http://github.com/Dziman
Дата: 21.01.14 17:25
Оценка:
Здравствуйте, Dair, Вы писали:

D> D>> Конфликтов git не выдавал, поэтому разработчик-1 ничего не заподозрил.


D> D>Я из самого реального вижу только что не бранч с изменениями вмержили в основную ветку, а основную ветку вмержили в бранч с изменениями.


D> О. Да нет, по истории всё ровно.


И диффы на каждом шаге нужные? В каком месте перестает быть видно изменение? Может быть где-то дальше эти изменения были удалены намеренно или не очень?
avalon 1.0rc3 build 430, zlib 1.2.5
Re[4]: Git: "более старая" версия перетирает "более новую" при мердже — почему?
От: Dair Россия https://dair.spb.ru
Дата: 21.01.14 17:30
Оценка:
D>И диффы на каждом шаге нужные? В каком месте перестает быть видно изменение? Может быть где-то дальше эти изменения были удалены намеренно или не очень?

Коммиты примерно так (пишу от руки, возможны опечатки):

#1: develop: Developer-1 branched 'develop' to 'Feature_1'
#2: develop: Developer-2 branched 'develop' to 'Feature_2'
#3: Feature_1: Developer-1 edited File1.cpp // дифф показывает внятные изменения только в File1.cpp
#4: Feature_2: Developer-2 edited File2.cpp // дифф показывает внятные изменения только в File2.cpp
#5: develop: Developer-2 merged 'Feature_2' to 'develop' // File1.cpp не менялся (логично), File2.cpp поменялся (логично)
#6: develop: Developer-1 merged 'Feature_1' to 'develop' // File1.cpp поменялся (логично), File2.cpp поменялся обратно на тот, который был в момент брэнча #1 и #2, это видно в диффе мерджа.
Re[5]: Git: "более старая" версия перетирает "более новую" при мердже — почему?
От: Dziman США http://github.com/Dziman
Дата: 21.01.14 19:14
Оценка:
Здравствуйте, Dair, Вы писали:

D> D>И диффы на каждом шаге нужные? В каком месте перестает быть видно изменение? Может быть где-то дальше эти изменения были удалены намеренно или не очень?


Вроде бы получилось добиться потери изменений в File1

D> Коммиты примерно так (пишу от руки, возможны опечатки):


D> #1: develop: Developer-1 branched 'develop' to 'Feature_1'

D> #2: develop: Developer-2 branched 'develop' to 'Feature_2'
D> #3: Feature_1: Developer-1 edited File1.cpp // дифф показывает внятные изменения только в File1.cpp
D> #4: Feature_2: Developer-2 edited File2.cpp // дифф показывает внятные изменения только в File2.cpp
D> #5: develop: Developer-2 merged 'Feature_2' to 'develop' // File1.cpp не менялся (логично), File2.cpp поменялся (логично)
#5.5 Feature_2: merge !!!-s ours!!! develop Восклицательные знаки для привлечения внимания
И тогда в #6 получается ff и имеем затертые изменения ветки Feature_1
D> #6: develop: Developer-1 merged 'Feature_1' to 'develop' // File1.cpp поменялся (логично), File2.cpp поменялся обратно на тот, который был в момент брэнча #1 и #2, это видно в диффе мерджа.

Судя по названиям веток используется git-flow? Тогда вероятнее всего используете какие-то скрипты и они могут делать такую магию по каким-то причинам. Например, проблема с переводами строк (autocrlf) (а при использовании в разных ОС это почти неизбежно)+ какой-нибудь GUI-клиент для git, который покажет 100500 изменений в каждой строке среди которых затеряется нужное. Или, как вариант, разработчик слышал что есть разные стратегии мержа, которые иногда работают лучше иногда хуже и получив конфликт попробовал другой, который очень отлично сработал
avalon 1.0rc3 build 430, zlib 1.2.5
Re[5]: Git: "более старая" версия перетирает "более новую" при мердже — почему?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 30.01.14 03:42
Оценка:
Здравствуйте, Dair, Вы писали:

D>#3: Feature_1: Developer-1 edited File1.cpp // дифф показывает внятные изменения только в File1.cpp

D>#4: Feature_2: Developer-2 edited File2.cpp // дифф показывает внятные изменения только в File2.cpp

Меня очень смущает слово "внятные". Были какие-то другие?

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

Поэтому, если реально таки у разработчиков что-то менялось в файлах, в которых не видно "внятного" изменения, то слияние вынуждено таки рассматривать изменение каждого файла в двух версиях от последнего общего корня (и хорошо ещё, если сюда не включаются перемещения содержимого).
Если Developer-1 что-то сделал с File2.cpp, "невнятное", но большое по объёму, и при слиянии применён не стандартный 3-way, то результат может быть любым.

Тут рядом спросили, что реально применяется — "родной" git или совместимые клиенты — это тоже может быть важным.

Для уточнения ситуации взять максимально родными средствами диффы File1.cpp на всех переходах (разработки и вокруг точек слияния).
The God is real, unless declared integer.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.