Как избежать конфликтов git в команде?

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

Как они работают с git в команде? Каким должен быть правильный поток, чтобы избежать конфликтов git?

Спасибо заранее.

8 ответов

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

  • Выполняем ли мы принудительные соглашения?
  • Если мы используем IDE, все ли они используют одинаковые настройки форматирования и ключевых слов? Например, Eclipse автоматически может завершить параметры.
  • Производим ли мы текстовые артефакты сборки? Например, мы минимизируем js, генерируем css-правила из файлов .sass или .scss или создаем xml-конфигурации на лету? Мы проверяем их?

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

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

# Enable the repository stock pre-commit hook
mv .git/hooks/pre-commit.sample .git/hooks/pre-commit

Этот крюк предварительной фиксации будет проводить серию проверок каждый раз при выпуске git commit, включая версию git diff --check, команду, которая проверяет, вносили ли ваши совершенные изменения ошибки в пробелах. Конец будет отклонен, если это произойдет. Если вам действительно нужно обойти это, вы можете выпустить git commit --no-verify, но не делать этого: Ошибки в виде пробелов похожи на неразорвавшиеся ординалы контроля версий. Они - конфликты слияния, ожидающие, чтобы это произошло.

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

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

Языки стилей, RequireJS и js minifiers также вызывают конфликты, если их сгенерированные объекты проверяются. Файлы, созданные этими технологиями, - это артефакты сборки. Вы не будете проверять архив WAR; не проверяйте SAS-скомпилированный файл CSS. Или, если вы считаете, вы должны использовать .gitattributes файл, чтобы git относиться к ним как к двоичным файлам.

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


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

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

Вне плана разработки нет возможности избежать конфликтов git, но это будет одна и та же проблема в любой системе управления версиями. Каждый раз, когда два человека меняют один и тот же раздел кода, вы должны выяснить, кто победит. Вот почему на самом деле не уместно смотреть на версию для решения, но посмотреть на свои методы и методы своей команды. Два автомобиля не могут пройти через перекресток в то же время, но очень сложно изобретать автомобили, которые могут проходить друг через друга, поэтому вместо этого мы изобрели системы управления стоп-сигналами и сигналами трафика. Это аналогичная проблема. Мы не можем сделать два изменения в одном и том же, не конфликтуем, поэтому мы должны контролировать, как мы работаем с файлами.

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


Существует только один способ избежать конфликтов: не нужно, чтобы разные люди редактировали один и тот же файл одновременно. По сути, у каждого файла есть владелец, который несет ответственность за все изменения и кто может передать право собственности другому. Собственность на файл может быть передана на основе определенной функции/ветки или изо дня в день, пока право собственности становится ясным.

Если вы обнаружите, что вы не можете дать одному владельцу каждому файлу, то:

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


Упорядочение.

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

Если вы вставляете новые вещи, это поможет определить, создаете ли вы конфликты.

Представьте список имен сотрудников

Andy, 
Oliver, 
Ivan,

Затем Брэд и Патрик присоединяются, и их имена добавляются в список. Вы добавляете Брэда, и я добавляю Патрика. Мы добавляем имена в нижнюю часть списка, а затем используем git для объединения наших списков. Результат будет знаком пользователям git: -

Merge branch 'Patrick' into Brad
Conflicts:
 names.txt
@@@ -1,4 -1,4 +1,8 @@@
 Andy, 
 Oliver, 
 Ivan,
 <<<<<<< HEAD
 +Brad,
 =======
+ Patrick,
 >>>>>>> Patrick

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

Andy,
Ivan,
Oliver,

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

Auto-merging names.txt
Merge made by the 'recursive' strategy.
 names.txt | 1 +
 1 file changed, 1 insertion(+)

И получим

Andy,
Brad,
Ivan,
Oliver,
Patrick,

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


Использовать начальный запуск блока

В программном обеспечении, подобном этому...

function chess() 
{
 while (!end_of_game)
 {
 make_move()

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

function chess() {
 while (!end_of_game) {
 make_move()

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

И комментарии к окончанию блоков

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

Если вы пишете много javascript и JSON, у вас может быть много строк, которые выглядят примерно так.

}
 }
 }
)

Если вы прокомментируете ситуацию, тогда они могут стать различимыми.

}
 }
 }
) // end of weekdays()

и

}
 }
 }
) // end of weekend()

больше не выглядят одинаково для git. Это поможет Git лучше понять ваши изменения. Если вы добавите что-то, например

function a()
{
 ...
} // end of a()

git, скорее всего, увидит это как единицу изменений и не подумает, что вы добавили что-то вроде

}
function a()
{
 ...

непосредственно перед концом некоторой другой функции. Даже если это не предотвращает конфликты, если Git видит и представляет ваши изменения разумно (т.е. Как мы мысленно их рассматриваем), тогда вы можете легко разрешать конфликты. Описательный заголовок, комментирующий, какие функции выполняют, параметры, которые они принимают, и т.д., Также поможет предотвратить Git от путаницы содержимого соседних функций.


Сообщите коллегам, когда вы нажали свои изменения

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

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

Использовать mergetool

Одной из целей Git является контроль версий. Другие программы специализируются на слиянии файлов и разрешении конфликтов. Если вы настроите mergetool для использования с git, тогда он может автоматически разрешать многие проблемы, которые Git рассматривает как конфликт, или, по крайней мере, делает очень хорошее предположение для вас, чтобы проверить и просто оставить нетронутым, если он выглядит нормально, или вы доверяете инструменту.

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

Использовать файлы меньшего размера

Я добавляю новый контроллер в нижней части mycontrollers.js, и вы добавляете новый контроллер в нижней части yourcontrollers.js: никаких проблем.

Мы добавляем новый контроллер в нижней части allcontrollers.js: conflict.

(Однако помните о том, как упорядочить вещи в алфавитном порядке. myNewController(), начиная с M, может находиться в середине файла, а вашNewController(), начиная с Y, может идти в конце того же файла, опять же без конфликтов. )


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

Даже тогда, в какой-то момент два человека будут редактировать один и тот же файл одновременно, не по своей вине. Очевидный вопрос, когда это происходит:

"Как я могу избавиться от устранения конфликтов git?

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

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


Используйте UTF-8, а не UTF-16 для текстовых файлов.

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

Как только Git считает файл двоичным файлом, он, вероятно, продолжит рассматривать файл как двоичный файл, даже если он изменен. Это означает, что контроль версий выполняется путем хранения полных версий файла, а не различий между ними, и некоторые преимущества системы управления версиями теряются. (Изменить: Нет. Я недавно протестировал это, изменив файл UTF-16 на UTF-8, выполнив его, отредактировав его и совершив снова - и начал обрабатывать изменения в виде текстовых изменений после того, как исходные и отредактированные файлы были UTF-8. )

Большинство современных редакторов распознают стиль кодировки символов и стиль окончания строки файла и сохраняют файл в том же формате. Некоторые редакторы (например, Babelpad) позволят вам выбрать, сохранять ли ваш файл в UTF-8 или UTF-16, а также с отметкой порядка байтов или без нее.

Если файл, который вы хотите контролировать с помощью версии (i) в формате UTF-16, и (ii) будет одинаково хорошо работать в UTF-8 - например, исходная программа для достойного современного компилятора - стоит рассмотреть преобразуя его в UTF-8.

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

(Примечание: файлы Linux, как правило, имеют UTF-8 по умолчанию. Некоторые программы для Windows имели привычку создавать UTF-16, поэтому пользователи Windows, скорее всего, будут иметь проблему. Также обратите внимание, что вы хотите исправить это перед самым первым фиксацией файла, прежде чем Git считает, что у него есть двоичный файл!)

Использовать Git rerere

Повторное использование записанного разрешения!

https://git-scm.com/book/en/v2/Git-Tools-Rerere

licensed under cc by-sa 3.0 with attribution.