Давайте снова поговорим про системы версионирования. Записал в нашей вики 3 мифа о Git.
piikummitus,
9000,
Alexey Gopachenko,
голова шимпанзе,
Ivan,
egor,
оленёнок Роршах,
insecure Bangalore,
go back in time,
BSOD blues,
словарный запас кофемолки,
...,
pgms,
псы в рапиде,
newtover,
sёliv,
and
je suis frf
liked this
Myth 1 — Git magically supports moves, renames, copies and everything will be just fine
- Igor Sereda
Myth 2 — git mv will take care of everything (that relates to renames/moves)
- Igor Sereda
Myth 3 — Git is consistent in how it handles change history
- Igor Sereda
Ну и в качестве обеспечения работы Git в режиме “летописи” (спасибо @9000 за меткий термин), пробую внедрить методику “separate commit for renames”. Отдельный коммит - только переименования и копирования, без каких-либо изменений, отдельный коммит c остальными изменениями.
- Igor Sereda
(Это, конечно, ужасно неудобно, я аж фичу запостил для IDEA - https://youtrack.jetbrains.com/issue... - там же подробная мотивация.)
- Igor Sereda
Кто-нибудь вообще так делает? И какие еще есть мифы о Git?
- Igor Sereda
разделять содержательные и несодержательные изменения кода по коммитам -- это, как мне до сих пор казалось, достаточно очевидная гигиеническая практика
- Evelynne
@mlivshin не очень понятно, что именно очевидно; у меня за пару часов рефакторинга может накопиться много изменений, в т.ч. переименований и переносов файлов; все эти изменения содержательны в равной мере
- Igor Sereda
эээ, ну понятно что в реальной жизни всё сложнее :)
- Evelynne
ну окей, это мифы — а реальность-то какова?
- псы в рапиде
define "magically", "just fine", "take care of everything", "consistent", "handles" :)
- псы в рапиде
В любой системе контроля версий люблю комитить отдельно любое маленькое изменение. Но не все команды это любят. Тогда приходится приспосабливаться.
- Джуник
@junique тут проблема в том, что даже самое маленькое изменение - например, переименование класса, чтобы исправить в имени опечатку - приходится делать в *два* коммита, если хочется 100% сохранения истории
- Igor Sereda
@squadette Реальность такова, что например параллельные rename и edit могут смержиться, а могут и не смержиться. Что касается определений, мифы написаны поэтическим языком и в определениях не нуждаются ;) , но я немного более подробно расписал проблему в фичареквесте для Идеи, ссылка выше. Если я что-то упускаю, или есть более простой способ решить проблему - буду рад разоблачениям, так как собираюсь внедрять двойной коммит в команде.
- Igor Sereda
я сразу скажу, что двойной коммит "сработает" только если смотреть на диффы между соседними коммитами. если сделать дифф между двумя коммитами, между которыми есть rename-commit, то Git опять "забудет" историю. на самом деле он ее никогда и не помнил. реально в гите просто каждый раз срабатывает rename detection между любыми двумя коммитами.
- псы в рапиде
Linus, конечно же, считает что это фича — типа это позволяет сделать генерилку диффов сколь угодно интеллектуальной. Вопрос в том что никто ее пока не сделал — но если есть "заказ", то ничто не мешает заняться этим вопросом.
- псы в рапиде
Мне кажется, что изложенный кейс — "переименовали и потом поменяли 99 строк, и при этом гит не определил что сотая строка — из первого файла" — этот кейс безумен, и я не ожидал бы такого поведения. если мы готовы идти по этой дорожке — то давайте тогда включать в редакторе трекинг cut-and-paste, чтобы понимать, что вот этот код переехал из одного класса в другой с исправлениями.
- псы в рапиде
Собственно, FAQ: https://git.wiki.kernel.org/index... в котором есть ссылка на письмо Линуса. он умный человек, к нему стоит прислушаться.
- псы в рапиде
Ага... если это так (rename detection не рекурсивный), тогда конечно это все не имеет смысла. Спасибо, надо проверить. Изложенный кейс конечно не жизненный, но демонстрирует inconsistency. Жизненных кейсов я уже набрал прилично за сравнительно недолгий срок работы с гитом, все они начинаются с момента wtf did just happen и дальше идет раскапывание, ну или потерянная история, когда мне blame на четырехлетний код выдает что это свежак от Васи недельной давности.
- Igor Sereda
К слову, blame очень важная вещь - не для обвинений, разумеется, а чтобы понять контекст "откуда взялась эта строчка, что было в коммит логе, и какие еще там были изменения"
- Igor Sereda
Может тебе будет лучше с hg?
- зона пингвинов
Линус умный человек безусловно и прислушаться стоит. Но воспринимать как догму все что он говорит я не готов. Надо еще раз перечитать, но по-моему, вполне очевидно, что информация теряется. Возможно, Линус не считает эту информацию важной, а я считаю.
- Igor Sereda
^^ а что hg, у него нет таких проблем? В любом случае, tooling не сравнить и мы плотно сели на stash
- Igor Sereda
от git blame надо читать документацию. чтобы он например не обращал внимания на whitespace, а также чтобы он тоже обрабатывал moved and copied lines.
- псы в рапиде
эх, я хотел добавить "конечно это не означает, что Линус безусловно и всегда прав во всем", но подумал что это типа очевидно. но нет! все же этот disclaimer нужен. а потом люди над юристами смеются. :(
- псы в рапиде
также на всякий случай хочу напомнить про команды git diff -B, -M, -C, --find-copies-harder
- псы в рапиде
^^ ну, ведь так же очевидно, что Линус умный, и к нему стоит прислушаться :)
- Igor Sereda
^^ да, спасибо, про опции эти в курсе, но они а) не находят существенно измененные копии, harder or not harder (ну или находят ерунду если указать -M05, например), б) не решают вопрос системно, так как их надо не забывать указывать каждому участнику процесса, и возможны вариации - один так указал, другой эдак
- Igor Sereda
Если про blame то читать вот http://jfire.io/blog...
- голос в темноте
Разве (в Git'е) renames / moves обнаружение работает на разном sha1 контента? Насколько мне известно - нет
- Maxim
не понимаю этот вопрос. а зачем нужно обнаружение renames/moves, если sha1 не поменялся? :) конечно работает.
- псы в рапиде
по мне так с гитом everything will be just fine. нет такой жопы, из которой нельзя выбраться. с svn и tfs периодически код просирался и все, ничего не сделаешь
- urquan
Вот да, в случае git потерять ничего практически нельзя, но иногда можно оказаться в положении, когда не-потерявшееся внезапно расположено чёрт знает где, и гадать, как оно туда попало. Часто такие случаи можно предупредить грубой силой, сказав -X ours, но не всегда.
- 9000
@9000 смотря как определить "потерять"; получить такое состояние, когда основная ветка вдруг *незаметно* оказывается без изменений, которые вносил один из разработчиков - done; потерять историю изменений конкретного кода из-за переименований - done уже много раз
- Igor Sereda
@berkus спасибо за ссылку на статью, но она нисколько не помогает, если blame -M/-C не сможет найти rename, потому что файл существенно поменялся (ключевое слово "существенно", что не является предсказуемой характеристикой с точки зрения программиста, меняющего код)
- Igor Sereda
@urquan хочется минимизировать вероятность жопы, путем ее четкого обозначения и придумывания формализуемых привычек, позволяющих ее избегать
- Igor Sereda
@squadette Вот черт, все куда больше запущено, чем я думал! Действительно, если у нас есть коммиты a--b--c, и мы делаем diff a c, git вообще не смотрит на b. Ну ладно, c diff понятно, но то же самое происходит и при merge - хотя при 3-way merge есть четкие пути изменений. "With the strategies that use 3-way merge (including the default, recursive), if a change is made on both branches, but later reverted on one of the branches, that change will be present in the merged result; some people find this behavior confusing. It occurs because only the heads and the merge base are considered when performing a merge, not the individual commits."
- Igor Sereda
Ну вот же ж шит. То есть double commit не поможет с merge никак :( При этом blame ведет себя лучше - показывает историю строчек и до переименований.
- Igor Sereda
ух ты! а вот про это я не знал. Надо подумать об этом.
- псы в рапиде
Я бы кстати предложил попробовать вместо стандартных мерджей сделать rebase. По дороге может получиться конфликт, но конфликтов бояться не надо. А история будет более понятной (потому что линейной).
- псы в рапиде
да, в этом свете rebase приобретает новый смысл... но Stash не поддерживает всасывание pull request'ов через rebase
- Igor Sereda
О, придумал - при мерже из A в B надо перебирать все коммиты от merge-base(A,B) до A, и последовательно накатывать их патчи (черрипикать?) на рабочий каталог, а потом закоммитить это как merge commit. И таки это будет то, как работает svn. >:-\
- Igor Sereda
Ну а какая разница? Один pull request можно и сырым гитом обработать. Я не верю что у вас в абсолютно всех пулл-реквестах встречается эта проблема.
- псы в рапиде
ну или пусть хозяин pull-реквеста сделает rebase относительно свежего мастера, и перепошлет его, и результат уже мерджить.
- псы в рапиде
тогда это и будет фактически "при мерже из A в B надо перебирать все коммиты от merge-base(A,B) до A, и последовательно накатывать их патчи (черрипикать?) на рабочий каталог, а потом закоммитить это как merge commit."
- псы в рапиде
P.S.: а, я понял логику про "if a change is made on both branches, but later reverted on one of the branches". интересно!
- псы в рапиде